《算法竞赛进阶指南》0x31质数 POJ2689 Prime Distance

题目链接:http://poj.org/problem?id=2689

左右区间位于int大范围内但是区间长度只有1e6,所以可以考虑先筛出根号R内的质数之后用这些质数去筛(L,R)区间的质数,筛的时候注意至少要从2*p开始,因为p为质数

在(L,R)区间内第一个p的倍数和最后一个p的倍数分别是(L/p)上取整*p 和 R/p下取整*p.

另外一个注意点就是,如果左边界是1的话,要筛掉1,因为1不是质数也不是合数,并且不会被使用的质数筛掉。

需要预处理出根号R下取整范围内的质数

代码

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
#define maxn 1000010
typedef long long ll;
#define M 46340
bool v[maxn];
const int inf=0x7fffffff;
vector<int> p ,ans;
int main(){
    memset(v,1,sizeof(v));//用0x01对每一个字节进行赋值 
    for(int i=2;i<=M;i++)
        if(v[i]){//没有被筛掉 
            p.push_back(i);
            for(int j=2;j<=M/i;j++)v[i*j]=0;//筛掉i的倍数 
        }
        
    ll  l,r;
    while(cin>>l>>r){
        memset(v,1,sizeof(v)); 
        ans.clear();
        if(l==1)v[0]=0;//1除去,不是合数也不是质数 
        
        for(ll i=0;i<p.size();i++)
        //最小的j=l/p[i]上取整,最大的j=r/p[i]下取整,保证 
            for(ll j=max((l+p[i]-1)/p[i],2ll);j<=r/p[i];j++){
                v[j*p[i]-l]=0;//计算偏移,将能被整除的数筛掉 
            }
            
            for(ll i=l;i<=r;i++){
                if(v[i-l])ans.push_back(i);
            }
            
            int minn=inf,maxx=0,x,y;
            for(int i=0;i+1<ans.size();i++){
                int num=ans[i+1]-ans[i];
                if(num>maxx){
                    maxx=num;
                    x=i;
                }            
                if(num<minn){
                    minn=num;
                    y=i;
                }
            }
            if(minn==inf)puts("There are no adjacent primes.");
            else printf("%d,%d are closest, %d,%d are most distant.\n",
                        ans[y],ans[y+1],ans[x],ans[x+1]);
    } 
}

猜你喜欢

转载自www.cnblogs.com/randy-lo/p/13177165.html