1. 程式人生 > >質數篩法 nsqrt(n)/nloglog(n)/n

質數篩法 nsqrt(n)/nloglog(n)/n

lap display 既然 技術 printf bre nlog play 隨筆

數論第一篇隨筆,就講一下質數篩法吧

質數,也稱做素數,在數學中有著重要的地位,有很多問題與算法都與質數有關(比如給你的hash函數選擇一個好的質數可以讓你的RP++)。對質數的最基本操作,就是輸出所有不大於n(n∈N*)的素數

最簡單的方法:首先逐個枚舉從 2 ~ n 的數a,分別模 2 ~ sqrt(a)(即a的平方,想一下為什麽只需要判到sqrt(a)),若余數為0,那麽a不是質數。

實現代碼:

技術分享
 1 #include<stdio.h>
 2 #include<math.h>
 3 int n;
 4 int main(){
5 scanf("%d",&n); 6 if(n<2){ 7 printf("0"); 8 return 0; 9 } 10 for(int i=2;i<=n;i++){ 11 bool f=true; 12 for(int j=2;j<=sqrt(i);j++) 13 if(i%j==0){ 14 f=false; 15 break; 16 }
17 if(f) printf("%d ",i); 18 } 19 return 0; 20 }
樸素算法

以上樸素算法復雜度為O(nsqrt(n))

既然叫做樸素算法,那肯定有效率比它高的算法,那就是篩法求質數

它是通過劃掉n內每個已求出質數的所有倍數來實現,留下來的數就都是不大於n的質數

舉個例子,我們要求不大於15的所有質數: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

1不是質數,2是最小的質數,從2開始劃掉2的倍數: 1 2 3 4 5 6

7 8 9 10 11 12 13 14 15

輪到3,3沒有被劃掉,是質數,所以劃掉3的倍數: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

然後依次是5、7、11、13,重復上面的步驟。

其實這種情況下在劃掉所有3的倍數時就已經求出了所有不大於15的質數,即沒有被劃掉的數

實現代碼:

技術分享
 1 #include<stdio.h>
 2 #include<string.h>
 3 #define maxn 2333333
 4 int n;
 5 bool zs[maxn];
 6 int main(){
 7     memset(zs,0,sizeof(zs));
 8     scanf("%d",&n);
 9     zs[0]=zs[1]=1;
10     for(int i=2;i*i<=n;i++)//i<=sqrt(n) ===>  i*i<=n
11        if(!zs[i])
12            for(int j=i+i;j<=n;j+=i) 
13         zs[j]=1;
14     for(int i=2;i<=n;i++)
15        if(!zs[i]) 
16        printf("%d ",i);
17     return 0;
18 }
質數篩法

這種做法的算法復雜度為O(nloglog(n))

那有沒有比以上效率更高的做法呢,有的!

如果按以上方法做,會有計算冗余,比如60這個數,會被2,3,5各篩一次

所有就有了下面復雜度為O(n)的方法

實現代碼:

技術分享
 1 #include<stdio.h>
 2 #include<string.h>
 3 #define maxn 2333333
 4 bool zs[maxn];
 5 int n,prime[maxn],num;
 6 int main(){
 7     memset(zs,0,sizeof(zs));
 8     scanf("%d",&n);
 9     zs[0]=zs[1]=1;num=0;
10     for(int i=2;i<=n;i++){
11         if(!zs[i]){
12             prime[++num]=i;
13             printf("%d ",prime[num]);
14         }
15         for(int j=1;j<=num&&i*prime[j]<=n;j++){
16             zs[i*prime[j]]=1;
17             if(!(i%prime[j])) break;
18         }
19     }
20     return 0;
21 }
質數的線性篩

這種方法就叫質數的線性篩法

詳細的以後再講吧

質數篩法 nsqrt(n)/nloglog(n)/n