poj 2689 Prime Distance

//先建立素数表,再用这些素数去筛掉[L,U]区间内的合数
#include <iostream> //线性筛素数
#include<cmath>
using namespace std;
#define maxn 46341 //floor(sqrt(double(INT_MAX))+0.5)=46341
bool isPrime[maxn+1];
int prime[10000],cnt;

void makePrime() //快速线性筛法建立素数表
{
memset(isPrime,true,sizeof(isPrime));
cnt=0;
for(int i=2;i<=maxn;i++)
{
if(isPrime[i])
prime[++cnt]=i;
for(int j=1; j<=cnt && i*prime[j]<=maxn; j++)
{
isPrime[i*prime[j]]=false;
if(i%prime[j]==0)
break;
}
}
}
int a,b,ans[100000],mark[1000002];
int main()
{
makePrime();
while(scanf("%d%d",&a,&b)!=EOF)
{
fill(&mark[0],&mark[b-a+1],1); //mark下标[0]-[b-a]对应于a-b,整个区间都初始化为素数,mark[x]=1表示x是素数
int tmp=floor(sqrt(double(b))+0.5);
__int64 i,j,k;
for(i=1;i<=cnt&&prime[i]<=tmp;++i)
{
j=a/prime[i]+(a%prime[i]>0); //要保证j*prime[i]>=a
if(j==1)
j++;
//j=1只有两种情况:(1)a=prime[i]是素数,筛除时应跳过a (2)a<prime[i],那么j也应该从prime[i]*2开始筛除合数,
//可以看到,筛除过程中k的下限必须大于或等于prime[i]*2

for(k=prime[i]*j;k<=b;k+=prime[i]) //第二次筛法,筛除掉区间内的合数
mark[k-a]=0; //j为合数
//当b=INT_MAX,在for循环最后一步k>b,会超int范围
}
if(a==1) //1不是素数,要另作处理
mark[0]=0;
int len=0;
for(k=a;k<=b;++k) //当b=INT_MAX,最后一步k>b,会超int范围
{
if(mark[k-a]==1)
ans[len++]=k;
}
if(len<2)
printf("There are no adjacent primes.\n");
else
{
int minv=INT_MAX,maxv=0,dis,posa,posb;
for(i=1;i<len;++i)
{
dis=ans[i]-ans[i-1];
if(minv>dis)
{
minv=dis;posa=i;
}
if(maxv<dis)
{
maxv=dis;posb=i;
}
}
printf("%d,%d are closest, %d,%d are most distant.\n",ans[posa-1],ans[posa],ans[posb-1],ans[posb]);
}
}
return 0;
}

posted on 2011-07-22 22:58  sysu_mjc  阅读(140)  评论(0编辑  收藏  举报

导航