線性篩法求素數
阿新 • • 發佈:2022-04-06
題目
給定一個正整數 n,請你求出 1∼n 中質數的個數。
輸入格式
共一行,包含整數 n。
輸出格式
共一行,包含一個整數,表示 1∼n中質數的個數。
資料範圍
1≤n≤1e6
輸入樣例:
8
輸出樣例:
4
埃氏篩法
時間複雜度:O(nloglogn)
思路:
(1)先把1刪除(現今數學界1既不是質數也不是合數)
(2)讀取佇列中當前最小的數2,然後把2的倍數刪去
(3)讀取佇列中當前最小的數3,然後把3的倍數刪去
(4)讀取佇列中當前最小的數5,然後把5的倍數刪去
(5)讀取佇列中當前最小的數7,然後把7的倍數刪去
(6)如上所述直到需求的範圍內所有的數均刪除或讀取
程式碼:
1 #include<iostream> 2 using namespace std; 3 const int N=1e6+10; 4 int prime[N],cnt; 5 bool st[N]; 6 void get_prime(int n) 7 { 8 for(int i=2;i<=n;i++) 9 { 10 if(!st[i]) 11 { 12 prime[cnt++]=i; 13 for(int j=i+i;j<=n;j+=i) st[j]=true; 14 } 15 16 } 17 } 18 int main() 19 { 20 int n; 21 cin>>n; 22 get_prime(n); 23 cout<<cnt<<endl; 24 return 0; 25 }
線性篩法
時間複雜度:O(n)
思路:
埃氏篩法中有些數是篩了多次的,有沒有什麼辦法使他只篩一次呢?(比如:12,在2的倍數時篩了一次,在3的倍數裡面也篩了一次)為此我們提出了線性篩法。
prime[]陣列中的素數是遞增的,當i能整除prime[j],那麼i*prime[j+1]這個合數
因為i中含有prime[j],prime[j]比prime[j+1]小,即i=k*prime[j],那麼i*prime[j+1]=(k*prime[j])*prime[j+1]=K*prime[j],
接下去的素數同理。所以不用篩下去了。
因此,在滿足i%prime[j]==0這個條件之前以及第一次滿足改條件時,
prime[j]必定是prime[j]*i的最小因子。
程式碼:
1 #include<iostream> 2 using namespace std; 3 const int N=1e6+10; 4 int prime[N],cnt; 5 bool st[N]; 6 void get_prime(int n) 7 { 8 for(int i=2;i<=n;i++) 9 { 10 if(!st[i]) prime[cnt++]=i; 11 for(int j=0;prime[j]<=n/i;j++) 12 { 13 st[prime[j]*i]=true; 14 if(i%prime[j]==0) break; 15 } 16 } 17 } 18 int main() 19 { 20 int n; 21 cin>>n; 22 get_prime(n); 23 cout<<cnt<<endl; 24 return 0; 25 }