1. 程式人生 > >素數篩法 埃氏篩 線性篩

素數篩法 埃氏篩 線性篩

素數篩法
呃~,太暴力的試1~sqrt(n)時候是因數就不說了。
這裡介紹埃氏篩和線性篩。

埃氏篩

埃氏篩主要原理是:
每次搜尋到一個質數將他的倍數標記為合數;
本質原理就是:一個合數一定表示為一個質數*一個數;

一些tips:
1、迴圈時從2-sqrt(n)就好,不然小心爆掉哦~

2、內層迴圈從i²開始:
假設x=i*k(k

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 10010
using namespace std;

int n,tot,p[maxn];
bool
check[maxn]; void prime() { memset(check,0,sizeof(check)); for(int i=2;i*i<=n;i++)//tip1:i=1-sqrt(n) { if(!check[i]) { p[++tot]=i; for(int j=i*i;j<=n;j+=i)check[j]=1;//tip2:j=i^2-n } } } int main() { n=1000; prime(); for
(int i=1;i<=tot;i++) printf("%d ",p[i]); }

然而,很顯然埃氏篩會重複判斷許多合數;
顯然,這並不優。

線性篩

線性篩較埃氏篩最大提高之處就在於它對於每一個數只會篩一次;
所以複雜度為O(n),這也是它名字的由來。

線性篩原理:
對於每一個數與質數表中的數相乘並標為合數;
然而這樣還是會重複……
所以對每一個i進行篩的時候如果i是質數的倍數,
那麼就跳出迴圈。

此做法可以保證是當i=a時a*b時篩去;
i=a*b;
所以b是i的最小質因數;
隨後就會跳出當前迴圈。
效率由此確定。

#include<iostream>
#include<cstring> #include<cstdio> #define maxn 100000 using namespace std; int n,tot,p[maxn]; bool check[maxn]; void prime() { check[1]=1; check[0]=1; for(int i=2;i<=n;i++) { if(!check[i])p[++tot]=i; for(int j=1;j<=tot&&i*p[j]<=n;j++) { check[i*p[j]]=1; if(!(i%p[j]))break;//*****關鍵 } } } int main() { n=1000; prime(); for(int i=1;i<tot;i++) printf("%d ",p[i]); }

ps:別忘了0,1,n的問題~~~~(表示被坑過)。