質數的兩種常用判斷方法——埃氏篩法和歐拉篩法


1.埃氏篩法:時間復雜度是O(nlognlogn),打表把一定范圍內的質數都記錄在數組里所以空間復雜度較高。具體的實現是通過兩個數組一個prime記錄當前范圍的質數序號,另一個isprime判斷是否是素數,將isprime初始化為1,從i=2開始遍歷標記所有i的倍數的數的isprime為零。

代碼:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<cstring>
 5 #include<cstdio>
 6 using namespace std;
 7 #define mem(s,n) memset(s,n,sizeof s);
 8 typedef long long ll;
 9 const int maxn=9e2+1;
10 const int Inf=0x7f7f7f7f;
11 bool isPrime[maxn];
12 int primes[maxn];
13 //當然,當數據太大導致普通數組存不下的時候,可以采用stl里的vector來存
14 int cnt;
15 void judgePri()
16 {
17     mem(isPrime, 1);
18     cnt = 0;
19     isPrime[1] = 0;//1特殊處理 
20     for (int i = 2; i < maxn; i++) 
21     {
22         if (isPrime[i] == 1)
23         {
24             primes[cnt++] = i;
25             for (int j = i; j < maxn; j += i) //標記i在N范圍內的所有倍數
26             {
27                 isPrime[j] = 0;
28             }
29         }
30     }
31 }
32  
33 int main(void)
34 {
35     judgePri();
36     for (int i = 0; i < cnt; i++)
37     {   
38         if(i%9==0) cout<<endl;
39         printf("%d ", primes[i]);
40     }
41     return 0;
42 }
View Code

 

然而我們會發現一個問題就是有重復標記的情況,舉個例子6第一次i=2時就已經標記了但是i=3又遍歷了一次,這樣其實就是浪費操作了,所以引入一種改進算法歐拉算法。

2.歐拉算法:時間復雜度O(n),主體思路還是建立在埃氏篩法的基礎上,對其重復標記進行了優化。我們很容易想到只用合數中的一個因數篩選掉這個合數。思路實現——利用前面求得的質數,從小到大遍歷如果i被prime[j]整除那么跳出循環,同時也把i*prime[j]遍歷了標記成合數。(具體實現見代碼)

代碼

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
using namespace std;
#define mem(s,n) memset(s,n,sizeof s);
typedef long long ll;
const int maxn=9e2+1;
const int Inf=0x7f7f7f7f;
bool isPrime[maxn];
int primes[maxn];
int cnt;
void judgePri() 
{
    int temp;
    mem(isPrime, 1);
    cnt = 0;
    isPrime[1] = 0;
    for (int i = 2; i < maxn; i++)
    {
        if (isPrime[i] == 1)
        primes[cnt++] = i;
        //優化
        for (int j = 0; j < cnt && (temp = i * primes[j]) < maxn; j++) //找i之前的所有質數 
        {
            isPrime[temp] = 0;//i * primes[j]肯定是合數,先標記掉 
            if (i % primes[j] == 0)//關鍵,每次整除一個最小的質數將會跳出循環,所以每個數字,只會被最小的質數篩一次 
            {
                break;
            }
        }
        //優化 
    }
}
 
int main(void)
{
    judgePri();
    for (int i = 0; i < cnt; i++)
    {   
        if(i%9==0) cout<<endl;
        printf("%d ", primes[i]);
    }
    return 0;
}
View Code

 3.常用板子:

 1 int  f[maxn];//f[i]表示i的因子個數
 2 int pri[maxn];
 3 int notpri[maxn];
 4 int prime[maxn];
 5 ll p[maxn]; // p[i] 表示 i由幾個素因子組成如 p[6]=2 2*3 p[8]=3 2*2*2
 6 void init(){
 7     now=0;f[1]=1;
 8     notpri[0]=notpri[1]=1;
 9     for(int i=2;i<=maxn-1;i++){
10         if(!notpri[i])pri[++now]=i,f[i]=2,p[i]=1;
11         for(int j=1;j<=now&&pri[j]*i<=maxn-1;j++){
12             notpri[i*pri[j]]=1;
13             if(i%pri[j]==0){//有pri[j]作為質因子時
14                 f[i*pri[j]]=f[i]*(p[i]+2)/(p[i]+1);
15                 p[i*pri[j]]=p[i]+1ll;
16                 break;
17             }
18             f[i*pri[j]]=f[i]*f[pri[j]];//互質則直接乘
19             p[i*pri[j]]=p[i]+1ll; 
20         }
21     }
22     // rep(i,1,10) {
23     //     cout<<i<<" "<<p[i]<<endl;
24     // }
25     rep(i,1,maxn-1) pre[i]=pre[i-1]+p[i];
26 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM