题目大意:给定正整数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; }