[英]How to find n as sum of dustinct prime numbers (when n is even number)
此問題為您提供一個小於或等於100000(10 ^ 5)的正整數。 您必須找出該號碼的以下內容:
一世。 是素數嗎? 如果它是質數,則打印是。
II。 如果數字不是質數,那么我們可以將數字表示為唯一質數的總和嗎? 如果可能,則打印是。 在這里,獨特的含義是,您只能一次使用任何質數。
如果以上兩個條件對於任何整數均失敗,則打印NO。 有關更多說明,請參見“輸入,輸出”部分及其說明。
輸入首先,您將得到一個整數T(T <= 100),它是測試用例的數量。 對於每種情況,您都將得到一個小於或等於100000的正整數X。
輸出對於每個測試用例,僅打印YES或NO。
樣本輸入輸出3 7 6 10是否是情況– 1說明:7是質數。
情況– 2說明:6不是質數。 6可以表示為6 = 3 + 3或6 = 2 + 2 +2。但是,任何質數都不能使用超過1次。 同樣,也沒有辦法將6表示為兩個或三個唯一質數之和。
情況– 3說明:10不是質數,但10可以表示為10 = 3 + 7或10 = 2 + 3 +5。在這兩個表達式中,每個質數僅使用一次。
在不使用任何數學技巧的情況下(不確定是否存在……您可能會想作為一個數學家,在這里我將有更多的見識),您將不得不遍歷所有可能的求和。 因此,您肯定需要遍歷所有可能的素數,因此,我建議第一步是找到最多10 ^ 5的所有素數。 一個基本的(Eratosthenes篩)[ https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes]可能已經足夠了,盡管如今存在更快的篩子。 我知道您的問題與語言無關,但是您可以將以下內容視為此類篩的矢量化偽代碼。
import numpy as np
def sieve(n):
index = np.ones(n+1, dtype=bool)
index[:2] = False
for i in range(2, int(np.sqrt(n))):
if index[i]:
index[i**2::i] = False
return np.where(index)[0]
還有其他一些簡單的優化方法,但是為簡單起見,這假設我們有一個數組index
,其中的索引與數字是否為質數完全對應。 我們從每個數字為質數開始,將0和1標記為非質數,然后對於每個質數,我們發現將其所有倍數標記為非質數。 最后的np.where()
僅返回索引,其中我們的索引對應於True
。
從那里,我們可以考慮一個實際解決您的問題的遞歸算法。 請注意,您可能可能需要大量不同的素數。 數字26是4個不同素數的總和。 它也是3和23的總和。由於4個素數的支票比2個素數的支票貴,我認為從最小的數目開始檢查是合理的。
在這種情況下,我們要做的方法是定義一個輔助函數,以確定一個數字是否恰好是k個素數的和,然后依次測試k的輔助函數從1到加數的最大可能數是。
primes = sieve(10**5)
def sum_of_k_primes(x, k, excludes=()):
if k == 1:
if x not in excludes and x in primes:
return (x,)+excludes
else:
return ()
for p in (p for p in primes if p not in excludes):
if x-p < 2:
break
temp = sum_of_k_primes(x-p, k-1, (p,)+excludes)
if temp:
return temp
return ()
通過此過程,首先我們檢查k
為1的情況(這是遞歸的基本情況)。 這與詢問x
是否為質數還是不在我們已經發現的質數之一中是相同的(元組excludes
,因為您需要唯一性)。 如果k
至少為2,則其余代碼將執行。 我們會檢查所有可能關心的素數,如果得到不可能的結果,則盡早停止(列表中的素數不小於2)。 我們對較小的k
遞歸調用相同的函數,如果成功,則將結果傳播到調用堆棧中。
請注意,我們實際上返回的是唯一素數附加元素的最小元組。 如果您希望答案指定為"NO"
,則此字段為空,但否則,您可以輕松提出為什么回答"YES"
。
partial = np.cumsum(primes)
def max_primes(x):
return np.argmax(partial > x)
def sum_of_primes(x):
for k in range(1, max_primes(x)+1):
temp = sum_of_k_primes(x, k)
if temp:
return temp
return ()
對於代碼的其余部分,我們存儲直到給定點的所有素數的部分和(例如,使用素數2、3、5,部分和將為2、5、10)。 這使我們可以輕松地檢查加數的最大可能數量。 該函數只是順序地檢查x
是否為素數,是否為2個素數,3個素數之和,等等。
作為一些示例輸出,我們有
>>> sum_of_primes(1001)
(991, 7, 3)
>>> sum_of_primes(26)
(23, 3)
>>> sum_of_primes(27)
(19, 5, 3)
>>> sum_of_primes(6)
()
乍一看,我認為緩存一些中間值可能會有所幫助,但我不相信會使用相同的參數兩次調用輔助函數。 可能有一種方法可以使用動態編程來執行大致相同的操作,但在具有最少計算量的表中可以防止使用遞歸進行任何重復的工作。 我不得不考慮更多。
至於您的老師所期望的確切輸出以及需要使用的編碼語言,這將取決於您。 希望這可以在算法方面有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.