给定整数a和b,请问区间[a,b)内有多少个素数?
a< b<=10^12
b-a<=10^6
输入
22 37
输出
3
输入
22801763489 2280178297
输出
1000
【分析】b以内的合数的最小质因数一定不超过sqrt(b)。如果有sqrt(b)以内的素数表的话,就可以把埃式筛法运用在[a,b)上了。也就是说,先分别做好[2,sqrt(b))的表和[a,b)的表,然后从[2,sqrt(b))的表中筛得素数的同时,也将其倍数从[a,b)的表中划去,最后剩下的就是区间[a,b)内的素数了。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
bool v[maxn],s[maxn];
int init(ll a,ll b)
{
for(int i=0;(ll)i*i<=b;i++)
v[i]=0;
for(int i=0;i<=b-a;i++)
s[i]=1;
//利用0~(a-b)代表a~b的数
for(ll i=2;i*i<=b;i++)
if(!v[i])
{
for(ll j=i+i;j*j<=b;j+=i)
v[j]=1; //筛[2,√b)
for(ll j=max(2ll,(a+i-1)/i)*i;j<=b;j+=i)
s[j-a]=0; //筛[a,b)
//j代表素数,j-a是将a~b变为0~b-a以便数组好存储
//2LL是2的长整形形式,与其比较意思是j最少是i的两倍
//((a+i-1)/i)*i得出的是(>=a && %i==0)离a最近的数,其实
//也可以写成a%i==0 ? a : (a/i+1)*i
}
int cnt=0;
for(int i=0;i<=b-a;i++)
if(s[i])
cnt++;
return cnt;
}
int main()
{
int t,h=1;
scanf("%d",&t);
while(t--)
{
ll a,b;
scanf("%lld%lld",&a,&b);
int cnt=init(a,b);
if(a==1)
cnt--;
printf("Case %d: %d\n",h++,cnt);
}
return 0;
}