(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...