1. 程式人生 > >區間內素數的個數(也要用到埃氏算法)

區間內素數的個數(也要用到埃氏算法)

-s true str i++ 限制 col 同時 ostream als

題目大意:給定正整數a和b,請問區間[a,b)內有多少個素數

限制條件:a<b<=10^12 b-a<=10^6

樣例:

22 37 3

22801763489 22801787297 1000

思路:由於b以內的合數的最小質因數一定不超過根號b,所以如果有根號b以內的素數表的話,就可以用埃氏算法運用在[a,b)上了。 也就是說,先分別做好[2,根號b)的表和[a,b)的表,

然後從[2,根號b)的表中篩得素數的同時,也將其倍數從[a,b)的表中劃去,最後剩下的就是[a,b)以內的素數了。

看代碼

#include<iostream>
#include<string
.h> #include<map> #include<cstdio> #include<cstring> #include<stdio.h> #include<cmath> #include<math.h> #include<algorithm> #include<set> #include<queue> typedef long long ll; using namespace std; const ll mod=1e9+7; const int maxn=1e6+10; const
int maxk=5e3+10; const int maxx=1e4+10; const ll maxe=1000+10; #define INF 0x3f3f3f3f3f3f #define Lson l,mid,rt<<1 #define Rson mid+1,r,rt<<1|1 ll l,r; bool is_prime[maxn],is_prime_small[maxn]; void solve() { ll sum=0; for(ll i=0;i*i<r;i++) is_prime_small[i]=false; for(ll i=0;i<r-l;i++) is_prime[i]=false
;//題目給的範圍太大,根本不可能開出那麽大的數組,所以用r-l來存儲 for(ll i=2;i*i<r;i++) { if(!is_prime_small[i]) { for(ll j=2*i;j*j<r;j+=i) is_prime_small[j]=true;//篩選[2,根號b)的表 for(ll j=max(i*2ll,l%i==0?l:(l/i+1)*i);j<r;j+=i)//為何是max(i*2ll,l%i==0?l:(l/i+1)*i),因為可能是第一個i*2,也有可能是後面的i*n*2,這就看l的值了 { if(!is_prime[j-l]) { is_prime[j-l]=true; // cout<<j<<" "; sum++; } } } } // cout<<endl; if(l==1) sum++;//註意這裏需要特判1 if(l==0)
{
if(r==1) sum+=1;
else sum+=2;//特判0
}
cout<<r-l-sum<<endl; } int main() { cin>>l>>r; solve(); return 0; }

區間內素數的個數(也要用到埃氏算法)