筛素数

来源:互联网 发布:饥荒mac联机破解版 编辑:程序博客网 时间:2024/06/10 02:38

poj  2869

题目大意:
给定区间[L,U],L和U可以很大,但区间长度不超过106
求这个区间中最近和最远的两对素数

 L and U (1<=L< U<=2,147,483,647)The difference between L and U will not exceed 1,000,000.

这题数据范围很大,不能直接打表,数组开不下啊达到2,147,483,647,可以先把sqrt(2,147,483,647)里的素数表打出来,然后用这个小素数表打出大的素数表,这样就轻松解决了!

#include<iostream>

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define N 46500
#define ll long long
using namespace std;
ll prime[N],next_prime[1001000];
bool isprime[N];
ll l,u;
void isp()
{
   ll i,j;
   memset(isprime,1,sizeof(isprime));
   isprime[0]=isprime[1]=0;
   isprime[2]=1;int p=0;
   prime[p++]=2;
   for(i=3;i<=N;i++)
   {
       if(isprime[i])
       prime[p++]=i;
       for(j=0;j<p&&i*prime[j]<=N;j++)
       {
           isprime[i*prime[j]]=0;
           if(i%prime[j]==0)
           break;
       }


   }
}
void next_isp()
{
    memset(next_prime,1,sizeof(next_prime));
    for(ll i=0,k;prime[i]*prime[i]<=u;i++)
    {
        k=l/prime[i]+(l%prime[i]>0);
        if(k==1)k=2;
        for(ll j=k*prime[i];j<=u;j+=prime[i])
        next_prime[j-l]=0;
    }
}
int main()
{
    ll i,j,temp,ans1,ans2,ans3,ans4,max1,min1;
    isp();
    while(scanf("%lld%lld",&l,&u)!=-1)
    {
       if(l==1)
       l=2;
       next_isp();
       min1=10000000;
       max1=-1;
       int flag=0;
       for(i=l;i<=u;i++)
       {
           if(next_prime[i-l])
           {
              flag++;
              if(flag>1)
              {
                  if(i-temp<min1)
                  {
                      min1=i-temp;ans1=temp;ans2=i;
                  }
                  if(i-temp>max1)
                  {
                      max1=i-temp;ans3=temp;ans4=i;
                  }
              }
              temp=i;
           }
       }
       if(flag<2)
       printf("There are no adjacent primes.\n");
       else
       printf("%lld,%lld are closest, %lld,%lld are most distant.\n",ans1,ans2,ans3,ans4);
    }
    return 0;
}