線性篩選素數法

2021-07-07 06:09:35 字數 1824 閱讀 8291

(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,就找到另乙個合數:

composite_num2 = pri_3*pri_4*pri_4*…*pri_n-1*pri_n。且maxdivisor2 <= n。

接續遍歷[1,n]中大於maxdivisor1的部分,一定會找到這個數:

maxdivisor2 = pri_4*pri_4*…pri_n-1*pri_n。因為n>=comsosite_num2>maxdivisor2

然後maxdivisor2乘以pri_3得到:

composite_num3 = pri_3*pri_4*pri_4*…*pri_n-1*pri_n*pri_3。

顯然composite_num3==composite_num2,這個合數被兩次篩掉,不能保證每個合數只被篩掉一次,就不能保證是線性時間複雜度。

本文給出的證明方法並不是很嚴格,很不嚴密,但是本文只是想解釋線性篩素數的演算法,並不是想嚴格證明,如果想看嚴格證明請看數論中的證明。另上面提到的線性篩素數的另一種說法,其實到這裡讀者應該差不多明白了,任何乙個合數都可分解為乙個素數和另乙個數(不一定是素數還是合數)的乘積。我們既然找到了這個合數最大的因數,那麼根據上面結論裡另乙個乘上的素數必然就是他的最小素因數。另一種說法只不過是換乙個說法罷了。

最後我們就可以得出結論:對於每乙個數i,乘上小於等於i的最小素因數的素數,就得到以i為最大因數的合數。設有乙個數t,只要將所有以比t小的數為最大因數的合數篩去,那麼比t小的數里剩下的就只有素數了。這就是線性篩法求素數的方法。

………………………………………………………………………………..2016.12.24更新……………………………………………………………..

想到了一種更好的理解思路:任何乙個合數都可以分解成若干個質數的乘積 :

composite_number = pri_1*pri_2*pri_3…*pri_n-1*pri_n

pri_1到pri_n一次遞增。

假設當前知道某個合數 composite_number2 = pri_3*pri_4*…*pri_n

composite_number2*pri_1 和composite_number2*pri_2都是以composite_number2為最大因數的合數。pri_1、pri_2都是小於composite_number2的最小素因數:pri_3

#include 

#include

#include

#include

using

namespace

std;

#define n 20

int flag[n+1],prime[n+1];

void getprime()

for(int j=0; j1;

if(i%prime[j]==0) break;//prime[j]是i的最小素因數,}}

for(int i=0;icout

<" ";

cout

//n個數,求第i個數之前有多少個質數

int table1(int n)

}for(int i=2;i<=n;i++)

if(p[i]==0)

p[i]=p[i-1];

}

素數線性篩選

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 效率改進不少了 但顯然還是不夠理想 繼續往下看 普通篩選法 埃拉託斯特尼篩法 先簡單說一...

素數篩選法

篩選素數法 搞acm的都知道,素數是數論中必不可少的知識,也是必須要掌握的,關於素數的篩選有好幾種方法,下面一一道來,寫的不好還請提出。第一種是最常規的做法 int main if j sqrt i cout 這種方法肯定是比第一種快的,至於快多少大家可以比較一下,注意到裡面的for迴圈是到sqrt...