數論二 Eular質數篩法

2022-05-08 04:36:08 字數 2484 閱讀 2034

時間限制:10000ms

單點時限:1000ms

記憶體限制:256mb

描述小ho:小hi,上次我學會了如何檢測乙個數是否是質數。於是我又有了乙個新的問題,我如何去快速得求解[1,n]這個區間內素數的個數呢?

小hi:你自己有什麼想法麼?

小ho:有!我一開始的想法是,自然我們已經知道了如何快速判定乙個數是否是質數,那麼我就直接將[1,n]之間每乙個數判定一次,就可以得到結果。但我發現這個方法太笨了。

小hi:確實呢,雖然我們已經通過快速素數檢測將每一次判定的時間複雜度降低,但是n個數字的話,總的時間複雜度依舊很高。

小ho:是的,所以後來我改變了我的演算法。我發現如果乙個數p是質數的話,那麼它的倍數一定都是質數。所以我建立了乙個布林型別的陣列 isprime,初始化都為true。我從2開始列舉,當我找到乙個isprime[p]仍然為true時,可以確定p一定是乙個質數。接著我再將n以內 所有p的倍數全部設定為isprime[p*i]=false。

寫成偽**為:

isprime = true

primecount = 0

for i = 2 .. n

if isprime[i] then

primecount = primecount + 1

multiple = 2

while (i * multiple ≤ n)

isprime[i * multiple] = false

multiple = multiple + 1

end while

end if

end for

小hi:小ho你用的這個演算法叫做eratosthenes篩法,是一種非常古老的質數篩選演算法。其時間複雜度為o(n log log n)。但是這個演算法有乙個冗餘的地方:比如合數10,在列舉2的時候我們判定了一次,在列舉5的時候我們又判定了一次。因此使得其時間複雜度比o(n)要 高。

小ho:那有沒有什麼辦法可以避免啊?

小hi:當然有了,乙個改進的方法叫做eular篩法,其時間複雜度是o(n)的。

輸入第1行:1個正整數n,表示數字的個數,2≤n≤1,000,000。

輸出第1行:1個整數,表示從1到n中質數的個數

樣例輸入

9
樣例輸出

4

開個bool陣列f記錄i是否為素數。
先全部賦為1,表示這個數為素數。
從2開始篩合數,若i為素數,則a*i,a∈z肯定為合數。
對於每乙個i,都去篩一遍,只篩素數倍,不篩合數倍,因為每個合數倍的都會被其他的比i大的數篩掉。
然後還有乙個優化,假設列舉到的素數為p,當p|i時就可以

break

了。

這樣可以保證每乙個合數k都是被k/它那個最小的質因數篩掉的,證明如下:
假設乙個合數

k=m*p1,p1

為其最小的質因子。則

k只會在

i=m,

primelist[j]=p1

時被篩掉一次。

首先會在

i=m,

primelist[j]=p1

時被篩掉是顯然的。因為p1是

k的最小質因子,所以

i=m的所有質因子也≥

p1。於是

j迴圈在列舉到

primelist[j]=p1

前不會break

,從而一定會在

i=m,

primelist[j]=p1

時被篩掉

其次不會在其他時候被篩掉。假設k在

i=n, primelist[j]=p2

時被篩掉了,此時有

k=n*p2。由於

p1是k最小的質因子,所以

p2 > p1

,m > n

且p1|n(

因為p2|m,n/p1==m/p2)

。則i=n,j

列舉到primelist[j]=p1時(

沒到primelist[j]=p2)

就break

了。所以不會有其他時候篩掉k。

1 #include

2 #include3 #include4 #include5 #include6 #include7 #include

8 #include9 #include10 #include11 #include12 #include13 #include14

#define maxn 1000010

15using

namespace

std;

16bool

f[maxn];

17int

su[maxn];

18int

main()

1932

}33 printf("%d"

,num);

34return0;

35 }

數論二 Eular質數篩法

如何去快速得求解 1,n 這個區間內素數的個數呢?自然我們已經知道了如何快速判定乙個數是否是質數,那麼我就直接將 1,n 之間每乙個數判定一次,就可以得到結果。雖然我們已經通過快速素數檢測將每一次判定的時間複雜度降低,但是n個數字的話,總的時間複雜度依舊很高。發現如果乙個數p是質數的話,那麼它的倍數...

hihocoder 數論二 Eular質數篩法

時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述小ho 小hi,上次我學會了如何檢測乙個數是否是質數。於是我又有了乙個新的問題,我如何去快速得求解 1,n 這個區間內素數的個數呢?小hi 你自己有什麼想法麼?小ho 有!我一開始的想法是,自然我們已經知道了如何快速判定乙...

Eular質數篩法

任意乙個正整數k,若k 2,則k可以表示成若干個質數相乘的形式。eratosthenes篩法中,在列舉k的每乙個質因子時,我們都計算了一次k,從而造成了冗餘。因此在改進演算法中,只利用k的最小質因子去計算一次k。而在其基礎上改進的eular篩法,其偽 為 isprime true primelist...