此问题为您提供一个小于或等于100000(10 ^ 5)的正整数。您必须找出该号码的以下内容:
i。是素数吗?如果它是质数,则打印是。
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。在这两个表达式中,每个质数仅使用一次。>
答案 0 :(得分:0)
在不使用任何数学技巧的情况下(不确定是否存在任何技巧...作为数学家,我想在这里会有更多的见识),您将必须遍历所有可能的求和。因此,您肯定需要遍历所有可能的素数,因此,我建议第一步是找到最多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"
,则此字段为空,否则,您可以轻松提出答案的答案。{p}
"YES"
对于代码的其余部分,我们存储到给定点的所有素数的部分和(例如,素数为2、3、5的部分和为2、5、10)。这使我们可以轻松地检查加数的最大可能数量。该函数只是顺序检查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个素数之和,等等。...
作为一些示例输出,我们有
x
乍一看,我认为缓存一些中间值可能会有所帮助,但我不相信会使用相同的参数两次调用辅助函数。可能有一种方法可以使用动态编程来执行大致相同的操作,但在具有最少计算量的表中可以防止使用递归进行任何重复的工作。我必须考虑更多。
就您的老师所期望的确切输出以及需要使用的编码语言而言,这取决于您。希望这可以在算法方面有所帮助。