题目链接:https://cn.vjudge.net/contest/70017#problem/M
题目大意:就是素数筛,但是要筛的数很大,但是筛的区间很小。
题解:先求出1e6的素数筛,然后看区间有三种可能,第一种是在1e6的范围里面,直接输出就行了,第二种就是最大的超过了1e6但是最小的小于1e6,第三种就是最小的超过了1e6,第二种和第三种的方法就是跟正常素数筛一样的求法,但是要利用映射的方法来统计区间内的素数。
代码:
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
using namespace std;
int Isprime[1000009];
int book[1000000],top=0,num;
bool vis[1000010];
void prime()
{
Isprime[0]=1;
Isprime[1]=1;
for(int i=2;i<=1000005;i++)
{
if(Isprime[i]==0)
{
book[++top]=i;
int x=i*2;
for(int j=3;x<=1000005;j++)
{
Isprime[x]=1;
x=i*j;
}
}
}
}
void solve(int a,int b)
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=top;i++)
{
int x=book[i];
if(x>=b) break;
for(int j=a/x;j<=b/x+1;j++)
{
if(j<=1) continue;
if(j*x>=a&&j*x<=b&&vis[j*x-a]==0)
{
vis[j*x-a]=1;
num++;
}
}
}
}
int main()
{
prime();
int t,a,b;
scanf("%d",&t);
for(int k=1;k<=t;k++){
scanf("%d %d",&a,&b);
num=0;
if(b>1e6){
solve(a,b);
printf("Case %d: %d\n",k,b-a+1-num);
}
else
{
int ans=0;
for(int i=1;i<=top;i++)
{
if(book[i]>=a&&book[i]<=b)
ans++;
}
printf("Case %d: %d\n",k,ans);
}
}
return 0;
}