素數的線性篩選

2021-07-05 06:43:35 字數 1928 閱讀 4332

出處:

線性篩選法之所以稱之為線性就是因為其對於每乙個合數只用其最小的素因子將其篩選出來。**如下:

#include #include #include #define maxn 1000000

using namespace std;

int p[1000005], pri[1000005], idx = -1;

void getprime()

for (int j = 0; j <= idx && pri[j]*i <= maxn; ++j) }}

printf("idx = %d\n", idx);

for (int i = 0; i <= 100; ++i)

}int main()

另一篇文章

出處:這個實際上就是先踢出了所有偶數,然後呢,以後要踢出的只能是奇數,否則你就重複預算了。k=2*i 是個偶數,i是奇數,3*i也是奇數,那麼每次t=i + k都是奇數。所以每次去除的都是奇數倍了。 

這樣處理後基本上每個數隻判斷一次就知道是不是素數了,所以是線性。。。

#include 02.#include 03.#include 04.int prime[100000];  

05.bool s[1000010];

06.

07.

08.void prime()//求素數

09.

26. }

27. }

28. k=1; prime[1]=2;

29. for (i=3;i<=1000000;i+=2)

30.

32. }

33. prime[0]=k;

34.}

下面這個程式:是簡化版的:

這個其實和上面那個是同乙個道理。首先f[i]==0就是素數,從2開始。然後我們要去除已經取得素數的i倍的數,f[p[j]*i] = 1;

關鍵就是下面那句話不好理解,因為正是那句跳出迴圈才能保證篩選素數是線性的。

為什麼i能除盡p[j]這個素數就跳出呢?

其實可以簡單證明一下:

合數可以由乙個質數數與另乙個數相乘得到

而同時假設合數a=質數b×質數c×乙個數d

令e=c × d,假設b ≥ c,e為合數,令f=d × b

a=f × c ,其中c

即大的質數和該合數的乘積可用乙個更大的合數和比其小的質數相乘得到

這也是if(!( i % prime[j]))break;的含義,這也是線性篩法算質數表的關鍵所在

舉個例子:

比如i = 9,現在素數是2 3 5 7

進入第二重迴圈了,f[2 * 9] = 1;f[3 * 9] = 1;

這個時候9%3==0,要跳出了,為什麼不做f[5* 9] =1;呢?

因為5 * 9 可以用3 * 15來代替,如果這個時候你計算了,那麼到i=15的時候這個數還會被重複計算一次,所以這裡大量避免了重複運算,所以也就節省了時間。

這裡總結一句話就是,乙個大的合數和這個能除盡的質數的乘積,一定能被乙個比起小的質數和合數更大的合數乘積來代替。

不懂的時候想想 5*9 = 5*3*3 = 3*15就是這個道理。

const int m = 3000500;  

02.int p[400010], pnum;

03.bool f[m];

04.void prime()

05.

09. for(j = 0; j < pnum && p[j] * i < m; j++ )

14. }

15.}





素數線性篩選

include include includeusing namespace std bool isprime 10000001 int pri 2000001 prin int findprime int maxn for int j 0 jmaxn break 當過大了就跳出 isprime i...

線性篩選素數

侵刪。題目 給出乙個正整數n,列印出所有從1 n的素數 即質數 關鍵是要找出乙個判斷乙個正整數n是否為素數的方法 傻瓜解法 n,n 2 1 include2 int main 3 12 這裡迴圈取到sqrt n 效率改進不少了 但顯然還是不夠理想 繼續往下看 普通篩選法 埃拉託斯特尼篩法 先簡單說一...

線性篩選素數法

pri 1到pri n遞增,composite num1 n 在遍歷 1,n 的數時,剛好maxdivisor1 pri 3 pri 4 pri n 1 pri n。pri 1是是它最小的質因數。maxdivisor如果乘以乙個大於pri 3的質因數,例如pri 4,就找到另乙個合數 composi...