POJ2689

题目连接:http://poj.org/problem?id=2689
转载请注明出处:http://hi.baidu.com/pub/show/createtext
题意:求某个区间内素数最近距离和素数最远距离

思路:二次筛选法
开始根据素数定理可知在最大范围的素数分布在50000的区间内,我们可以求出在这范围内的素数,这是第一次筛选
void doprime1()
{
    numprime1=0;
    memset(isprime,true,sizeof(isprime));
    isprime[1]=false;
    for(long long i=2; i<maxn; i++)
    {
        if(isprime[i])
        {
            prime1[++numprime1]=i;
            for(long long j=i*i; j<maxn; j+=i)
            {
                isprime[j]=false;
            }
        }
    }
}
由于数据较大  我们必须在[l,u]之间在把这个区间的素数筛选出来,通过开始的素数表吧[l,u]的非素数排除掉
void doprime2()
{
    long long b;
    long long j;
    memset(isprime,true,sizeof(isprime));
    for(int i=1; i<=numprime1; i++)
    {
        b=l/prime1[i];
        while(b*prime1[i]<l||b<=1)
            b++;
        for(j=b*prime1[i]; j<=u; j+=prime1[i])
        {
            if(j>=l)
            {
                isprime[j-l]=false;
            }
        }
    }
    if(l==1)
    {
        isprime[0]=0;
    }
AC Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<climits>
using namespace std;
const int maxn=50000;
const int maxm=99999999;

bool isprime[maxn*20];
int prime1[maxn];
int numprime1;
void doprime1()
{
    numprime1=0;
    memset(isprime,true,sizeof(isprime));
    isprime[1]=false;
    for(long long i=2; i<maxn; i++)
    {
        if(isprime[i])
        {
            prime1[++numprime1]=i;
            for(long long j=i*i; j<maxn; j+=i)
            {
                isprime[j]=false;
            }
        }
    }
}

long long l,u;
long long prime2[1000001];
int numprime2;
void doprime2()
{
    long long b;
    long long j;
    memset(isprime,true,sizeof(isprime));
    for(int i=1; i<=numprime1; i++)
    {
        b=l/prime1[i];
        while(b*prime1[i]<l||b<=1)
            b++;
        for(j=b*prime1[i]; j<=u; j+=prime1[i])
        {
            if(j>=l)
            {
                isprime[j-l]=false;
            }
        }
    }
    if(l==1)
    {
        isprime[0]=0;
    }
}

void solve()
{
    long long minr,minl,maxr,maxl;
    long long mmin=maxm,mmax=0;
    doprime2();
    numprime2=0;
    for(int i=0; i<=u-l; i++)
    {
        if(isprime[i])
        {
            prime2[++numprime2]=i+l;
        }
    }
    if(numprime2<=1)cout<<"There are no adjacent primes."<<endl;
    else
    {
        for(int i=1; i<numprime2; i++)
        {
            if(prime2[i+1]-prime2[i]>mmax)
            {
                mmax=prime2[i+1]-prime2[i];
                maxl=prime2[i];
                maxr=prime2[i+1];
            }
            if(prime2[i+1]-prime2[i]<mmin)
            {
                mmin=prime2[i+1]-prime2[i];
                minl=prime2[i];
                minr=prime2[i+1];
            }
        }
        cout<<minl<<","<<minr<<" are closest, "<<maxl<<","<<maxr<<" are most distant."<<endl;
    }
}

int main()
{
    doprime1();
    while(cin>>l>>u)
    {
        solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值