埃式篩法:給定一個正整數n(n<=10^6),問n之內有多少個素數?ios
作法:作法其實很簡單,首先將2到n範圍內的整數寫下來,其中2是最小的素數。將表中全部的2的倍數劃去,表中剩下的最小的數字就是3,他不能被更小的數整除,因此3是素數。再將表中全部的3的倍數劃去……以此類推,若是表中剩餘的最小的數是m,那麼m就是素數。而後將表中全部m的倍數劃去,像這樣反覆操做,就能依次枚舉n之內的素數,這樣的時間複雜度是O(nloglogn)。spa
題解:若是要是按照一個一個判斷是不是素數而後把ans+1,時間複雜度爲O(n√n),對於10^6的數據時間複雜度就是O(10^9),一定會超時,但此時埃氏篩法的時間複雜度只有O(nloglogn)。code
int prime[MAXN];//第i個素數 bool is_pri[MAXN+10];//is_pri[i]表示i是素數 //返回n之內素數的個數 int sieve(int n){ int p=0; for(int i=0;i<=n;i++)is_pri[i]=true; is_pri[0]=is_pri[1]=false; for(int i=2;i<=n;i++){ if(is_pri[i]){ prime[++p]=i; for(int j=2*i;j<=n;j+=i)is_pri[j]=false; } } return p; }
區間素數篩:給定兩個正整數a、b(a<b<=10^十二、b-a<=10^6),請問[a,b)內有多少個素數?blog
主要思想:既然在以前已經講過b之內的和書的最小質因數不會超過√b。若是有√b之內的素數表的話,就能夠把埃氏篩法運用在上面了。也就是說,咱們能夠先分別作好[2,√b)的表和[a,b)而後在第一個表的是素數的前提下,刪去第二個表中的數便可。get
#include<iostream> using namespace std; bool pri[1000000+10]; bool ispri[10000000+10];//ispri[i-a]=true表明i是素數 void getpri(){ memset(pri,true,sizeof(pri)); pri[0]=pri[1]=0; for(int i=2;i<=1000000;i++){ if(pri[i]){ for(int j=2*i;j<=1000000;j+=i)pri[j]=0; } } } int main(){ long long a,b; scanf("%lld%lld",&a,&b); getpri(); memset(ispri,true,sizeof(ispri)); for(long long i=2;i*i<b;i++){ if(pri[i]){ for(long long j=max((a+i-1)/i,2LL)*i;j<b;j+=i) ispri[j-a]=0; } } long long cnt=0; for(int i=0;i<b-a;i++)if(ispri[i])cnt++; if(a==1)cnt--; printf("%lld\n",cnt); }