【问题标题】:reporting all prime numbers less than n报告所有小于 n 的素数
【发布时间】:2012-03-15 07:04:05
【问题描述】:

我需要打印所有小于给定数 n 的素数。我可以使用 Eratothenes 的筛子,但该算法的运行时间不是 O(n)。这个问题有O(n)时间解吗?

【问题讨论】:

    标签: primes


    【解决方案1】:

    埃拉托色尼筛法的时间复杂度为 O(n log log n)。函数 log log n 增长非常缓慢;例如,log(log(10^9)) = 3。这意味着您可以有效地将时间复杂度的 log log n 部分视为常数,并忽略它,给出“几乎” O(n) 的时间复杂度.

    有多种算法可以在 O(n) 或 O(n / log log n) 时间内运行,包括 Pritchard 轮筛和 Atkins 筛。但常数因素通常会使这些算法在实践中比埃拉托色尼筛法慢。除非您需要极高的速度,并且您知道自己在做什么,并且愿意花费大量时间去做,否则实际的答案是埃拉托色尼筛。

    您的问题是要打印素数列表。在这种情况下,输出将支配您选择的任何算法的运行时间。所以帮自己一个忙,实现一个简单的 Eratosthenes 筛。

    【讨论】:

      【解决方案2】:

      我认为您不会找到一种算法来检查具有 O(n) 时间复杂度的 任意 数的素性。我很确定 NSA(以及任何其他处理加密问题的组织)不会对此很满意 :-)

      获得 O(n) 或更好的方法的唯一方法是预先计算(例如)前 5000 万个素数(或使用 someone else's already-precalculated list)并将其用作查找。我在本地有这样一个文件,只需在其上运行grep 即可查看该数字是否为素数。它对任意数字没有帮助,但我很少需要使用那么大的数字。当然,加密货币的人会认为这样一个列表对于他们的目的来说太小了。

      而且,如果将其转换为位图(前 500 万个素数约为 120M),您甚至可以通过简单地将数字转换为字节偏移量和位掩码将复杂度降低到 O(1) - 一对位移和/或按位运算。

      但是,在 O(n) 时间复杂度中,获得低于某个n 的素数的列表 肯定是可行的。 Atkin and Bernstein paper 详细说明 Sieve of Atkin 声明:

      我们引入了一种算法,该算法使用O(N/log(log(N))) 加法计算最多为 N 的素数 ...

      这实际上比 O(n) 略

      但是,它仍然不太可能与查找解决方案竞争。我的建议是使用 Atkin 或 Eratosthenes 来制作一个列表 - 这并不重要,因为您只会这样做一次,因此性能并不重要。

      然后使用列表本身来检查素数。

      【讨论】:

      • 根据您的硬件和程序,有时筛选比从磁盘读取列表更快。快速的汇编器实现将击败慢速磁盘。
      • 我不太确定 我的grep 用于第 50 百万个素数的时间不到半秒。筛子花费了 1 分 10 秒,尽管可以说它现在知道低于该数字的 所有 素数,但使用稍微复杂的搜索词或使用 @ 的 grep 解决方案也是如此987654330@ 获取行号,head 将它们全部打印出来)。特定值的试除法要快得多,但是一旦您离开本机整数领域并使用 bignum 库,这可能会减慢很多。
      • 快盘慢筛。 ;) 我不太确定今天磁盘是否真的很快,但筛子肯定很慢。我在 Haskell 中的分段 Eratosthenes 型筛子在 3.2 秒内找到了第 50 百万个素数,D.J.伯恩斯坦的素数在 0.5 秒内找到它。 (但如果我真的想要第 n 个素数而不是前 n 个素数,我会使用更快的方法。)
      • 使用素数估计公式在二进制文件(或任何具有固定宽度表示的整数)上查找素数应该是 O(1)。更多这里stackoverflow.com/a/4709871/849891 .
      • 注意:Atkin 和 Bernstein 的论文指的是对 Atkin 的基本 Sieve 的深奥改编,这将把渐近计算复杂度从 O(n) 提高到 O(n / log log n) 但我的知识从来没有实现过这种特殊的“格点”技术,包括它的作者。通常实现的 SoA 是 O(n),比 SoE 的通常 O(n log log n) 要好。速度不依赖于大 O 性能,因为 Pritchard 轮筛具有 O(n / log log n) 性能并且可以实现,但具有抵消增益的常数因子开销。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-18
      • 2011-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多