gpt4 book ai didi

algorithm - 是否有快速、实用的素数生成器?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:33:40 25 4
gpt4 key购买 nike

假设我有一个自然数 n,并且我想要一个包含 n 以内的所有素数的列表(或其他任何内容)。

经典的素数筛算法在 O(n log n) 时间和 O(n) 空间内运行——它适用于更多命令式语言,但需要 in-以基本的方式对列表和随机访问进行修改。

有一个涉及优先级队列的功能版本,非常漂亮——你可以看看here .这在大约 O(n/log(n)) 时具有更好的空间复杂度(渐近更好,但在实际规模上值得商榷)。不幸的是,时间分析很糟糕,但它非常接近 O(n^2)(实际上,我认为它大约是 O(n log(n) Li(n)) ,但是 log(n) Li(n) 大约是 n)。

从渐近的角度来说,使用连续的试验除法在生成每个数字时检查其素数实际上会更好,因为这只需要 O(1) 空间和 O (n^{3/2}) 次。有没有更好的办法?

编辑:事实证明我的计算完全不正确。文章中的算法是O(n (log n) (log log n)),文章对此进行了解释和证明(见下面的答案),而不是我上面放的复杂的乱七八糟的。如果有一个真正的 O(n log log n) 纯算法,我仍然很乐意看到。

最佳答案

这是 Melissa O'Neill 算法的 Haskell 实现(来自链接文章)。与 Gassa 链接到的实现不同,我尽可能少地使用惰性,因此性能分析很清楚——O(n log n log log n),即 n log log 中的线性对数n,命令式埃拉托色尼筛法进行的写入次数。

堆实现只是一个锦标赛树。平衡逻辑在push;通过每次交换子树,我们确保对于每个分支,左子树的大小与右子树的大小相同或大一倍,从而确保深度为 O(log n)。

module Sieve where

type Nat = Int

data Heap = Leaf !Nat !Nat
| Branch !Nat !Heap !Heap
deriving Show

top :: Heap -> Nat
top (Leaf n _) = n
top (Branch n _ _) = n

leaf :: Nat -> Heap
leaf p = Leaf (3 * p) p

branch :: Heap -> Heap -> Heap
branch h1 h2 = Branch (min (top h1) (top h2)) h1 h2

pop :: Heap -> Heap
pop (Leaf n p) = Leaf (n + 2 * p) p
pop (Branch _ h1 h2)
= case compare (top h1) (top h2) of
LT -> branch (pop h1) h2
EQ -> branch (pop h1) (pop h2)
GT -> branch h1 (pop h2)

push :: Nat -> Heap -> Heap
push p h@(Leaf _ _) = branch (leaf p) h
push p (Branch _ h1 h2) = branch (push p h2) h1

primes :: [Nat]
primes
= let helper n h
= case compare n (top h) of
LT -> n : helper (n + 2) (push n h)
EQ -> helper (n + 2) (pop h)
GT -> helper n (pop h)
in 2 : 3 : helper 5 (leaf 3)

关于algorithm - 是否有快速、实用的素数生成器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42118496/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com