题目:xmu1246
方法:数论 两次素数筛选
思想:<根据L,U相差不超过100000,将[L,U]之间所有的素数找出来。
因为要筛掉2147486347内所有的非素数。所以需要知道该区间内所有非素数的素数因子。
而这些素数因子应当在sqrt(2147483647)=46340之内。
所以预先将46340以内所有的素数找出来,然后用这些素数去筛掉[L,U]区间内的非素数。
参见 :huicpc9527
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAX 0x0ffffff
__int64 pri[50010];//用数组直接存<47000的素数
__int64 num;
bool tag[50010];
bool mark[1050010];//区间相对位置是否为素数
void prime() //求小于sqrt(2147483647)以内的素数
{
memset(tag,true,sizeof(tag));
num=0;
for(int i=2; i<=47000; i++)
{
if(tag[i])
{
pri[num++]=i;
if(i<47000/i)
for(int j=i*i; j<=47000; j+=i)
tag[j]=false;
}
}
}
int main()
{
__int64 st,en,i,j,k;
prime();
int t;
cin>>t;
while(t--)
{ scanf("%I64d%I64d",&st,&en);
if(st==1)st=2;
memset(mark,true,sizeof(mark));
for(i=0; i<num&&(__int64)(pri[i])*pri[i]<=en; i++)//第二次筛选求区间素数
{
k=st/pri[i]+(st%pri[i]!=0);
if(k==1)k++;
for(j=k*pri[i]; j<=en; j+=pri[i])
mark[j-st]=false;
}
__int64 ans=0;
for(i=0;i<=en-st;i++)
if(mark[i])ans++;
printf("%I64d\n",ans);
}
return 0;
}