埃氏篩法(素數篩)

  1. 埃式篩法:給定一個正整數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;
}
  1. 區間素數篩:給定兩個正整數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);
    }
相關文章
相關標籤/搜索