【问题标题】:How to find n as sum of dustinct prime numbers (when n is even number)如何找到 n 作为不同素数的总和(当 n 是偶数时)
【发布时间】:2019-01-25 08:43:26
【问题描述】:

这个问题给你一个小于或等于 100000 (10^5) 的正整数。您必须找出该号码的以下内容:

我。数是素数吗?如果是素数,则打印 YES。

二。如果这个数不是素数,那么我们可以将这个数表示为唯一素数的总和吗?如果可能,则打印 YES。这里唯一的意思是,任何质数只能使用一次。

如果以上两个条件对于任何整数都失败,则打印 NO。如需更多说明,请参阅输入、输出部分及其解释。

输入 首先给定一个整数 T (T

输出 对于每个测试用例,只打印 YES 或 NO。

示例 输入输出 3 7 6 10 是 不 是的 案例 - 1 解释:7 是一个素数。

Case – 2 解释:6 不是质数。 6 可以表示为 6 = 3 + 3 或 6 = 2 + 2 + 2。但你不能使用任何质数超过 1 次。也没有办法将 6 表示为两个或三个唯一素数的总和。

Case – 3 解释:10 不是素数,但 10 可以表示为 10 = 3 + 7 或 10 = 2 + 3 + 5。在这两个表达式中,每个素数只使用一次。

【问题讨论】:

  • 问题到底是什么?您是在寻求有效解决问题的提示、在合理时间内运行的算法、C++ 实现,还是如何解决代码中的编译错误?
  • 看起来像(作业/比赛)问题转储。你有什么想法/尝试吗?
  • 是的,我要求的是短时间代码...我正在制作一个 O(3)

标签: functional-programming


【解决方案1】:

在不使用任何数学技巧的情况下(不确定是否存在......作为一名数学家,您会认为我会在这里有更多的见解),您将不得不迭代所有可能的求和。因此,您肯定需要遍历每个可能的素数,所以我建议第一步是找到最多 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)
()

乍一看,我认为缓存一些中间值可能会有所帮助,但我不相信辅助函数会使用相同的参数调用两次。可能有一种方法可以使用动态编程来做大致相同的事情,但在一个计算量最少的表中,以防止递归的任何重复工作。我不得不考虑更多。

至于您的老师期望的确切输出以及需要编码的语言,这将取决于您。希望这对算法方面有所帮助。

【讨论】:

    猜你喜欢
    • 2015-12-24
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    • 2022-11-17
    相关资源
    最近更新 更多