ACWing 868 篩質數(配數學證明)

2021-10-19 10:39:58 字數 1820 閱讀 4137

給定乙個正整數n

nn,求1∼n

1\sim n

1∼n中質數的個數。

輸入格式:

共一行,包含整數nnn。

輸出格式:

共一行,包含乙個整數,表示1∼n

1\sim n

1∼n中質數的個數。

資料範圍:

1 ≤n

≤106

1\le n\le 10^6

1≤n≤10

6法1:埃拉託斯特尼篩法。從2

22開始遍歷到n

nn,每次篩去當前數的倍數(不包括自己,只包括乘以2,3

,...

2,3,...

2,3,..

.

#include

using

namespace std;

const

int n =

1000010

;int primes[n]

, res;

// st[i]表示i被篩掉了(即不是質數,是合數)

bool st[n]

;void

get_primes

(int n)}}

intmain()

空間複雜度o(n

)o(n)

o(n)

,時間複雜度需要計算n∑p

≤n1p

n\sum_\frac

np≤n∑​

p1​可以參考解析數論的結論,時間複雜度是o(n

log⁡

log⁡n)

o(n\log \log n)

o(nlog

logn)。

法2:尤拉篩(線性篩)。這個篩法的思路是讓每個合數只被其最小質因子篩。**如下:

#include

using

namespace std;

const

int n =

1000010

;int primes[n]

, res;

bool st[n]

;void

get_primes

(int n)}}

intmain()

時空複雜度o(n

)o(n)

o(n)

(由於每個數隻會被其最小素因子篩,所以每個數隻會被篩一次,所以時間複雜度是o(n

)o(n)

o(n)

)。注:

1、對於下面這句:

st[primes[j]

* i]

=true

;

這句在執行的時候,primes[j]一定是primes[j] * i的最小素因子,因為如果不是的話,在if (i % primes[j] == 0) break;這句裡,當primes[j]列舉到i的最小素因子的時候,就會break出來了,這就矛盾了。所以就證明了每個被篩掉的數一定是被其最小素因子篩的。

2、對於任意合數n

nn,設其最小素因子是p

pp,當i列舉到n/p

n/pn/

p的時候,在內層for迴圈裡一定會在break之前就把n

nn篩掉,因為n/p

n/pn/

p的最小素因子最小就是p

pp,所以在primes[j]列舉到p

pp之前,是不會break的。這就證明了任意合數一定會被篩掉。

質數 篩質數

質數定理 1 n中質數有n ln n 個質數 按順序刪除每個數的倍數,最後剩下的就是質數。給定乙個正整數n,請你求出1 n中質數的個數。輸入格式 共一行,包含整數n。輸出格式 共一行,包含乙個整數,表示1 n中質數的個數。資料範圍 1 n 1061 n 106 輸入樣例 8輸出樣例 4 includ...

3 篩質數 質數

篩質數的核心思想 先把所有數放進乙個陣列 然後從前往後看,把每乙個數的倍數刪掉 第乙個數是2,就把所有2的倍數刪掉,4,6,8,10,12 第二個數是3,就把所有3的倍數刪掉,6,9,12 第二個數是4,就把所有4的倍數刪掉,8,12 第二個數是5,就把所有5的倍數刪掉,10 以此類推 這樣篩完之後...

判斷質數與篩質數

一 判定質數 要判斷乙個數是不是質數,只需遍歷小於等於它的所有數,如果它能被除了1和本身之外的數整除,那麼它就不是質數。很簡單,暴力列舉,如下 1 bool is prime intx 2 但是還可以優化,對於乙個數 x 它有乙個約數 d 那麼 frac 也是 x 的約數,所以我們只需要列舉較小的乙...