給定乙個正整數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
logn)
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 的約數,所以我們只需要列舉較小的乙...