POJ-2689 Prime Distance(筛素数的平移)

本文详细解析了POJ-2689 Prime Distance问题,介绍了通过两次筛选素数的方法来找出指定区间内相邻素数之间的最小与最大距离。首次筛选2^16以内的素数,第二次则通过对筛法进行区间平移,从区间的左端点开始筛选。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  题目:POJ-2689 Prime Distance

  题目大意:给定一个区间[l,r],让求区间当中相邻素数组中距离最小的一组素数以及距离最大的一组素数。

  解题思路:分析一下数据发现,虽然区间的右端点的最大值可以达到2^32左右,但是,区间的跨度确实极小的,应用这个,可以通过筛两次素数,第一次正常筛出2^16以内的素数,第二次对筛法进行区间平移,从区间的左端点开始筛除即可。这里注意左端点的处理:

  1.l=(x-1)/prime[i]+1,因为x本身可能是prime[i]的倍数,若不减去1直接在最后加1可能就忽略了区间的左端点,排除这种情况先进行x-1操作。

  2.(l<2)l=2,小于2第一个数就刚好是prime[i],这时从下一个数开始筛。

  AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 100010
using namespace std;
bool visit[maxn];
int prime[maxn];
int total;
bool q[1000010];
void getprime(){
    int i,j;
    total=0;
    memset (visit,0,sizeof(visit));
    for (i=2;i<maxn;i++){
        if (visit[i]==0){
            prime[++total]=i;
            for (j=2*i;j<maxn;j+=i){
                visit[j]=1;
            }
        }
    }
}
int main(){
    int i,j,x,y;
    getprime();
    while (scanf("%d%d",&x,&y)!=EOF){
        memset (q,0,sizeof(q));
        for (i=1;i<=total&&prime[i]<=y;i++){
            int l=(x-1)/prime[i]+1;
            if (l<2)l=2;
            int r=y/prime[i];
            for (j=l;j<=r;j++){
                q[j*prime[i]-x]=1;
            }
        }
        int minn=1000100,maxx=0,pre=-1,y1,y2;
        for (i=0;i<=y-x;i++){
            if (q[i]==0){
                if (pre!=-1){
                    int dis=i-pre;
                    if (minn>dis){
                        minn=dis;
                        y1=i;
                    }
                    if (maxx<dis){
                        maxx=dis;
                        y2=i;
                    }
                }
                if (i+x!=1)pre=i;
            }
        }
        if (minn==1000100&&maxx==0){
            printf("There are no adjacent primes.\n");
        }
        else {
            int x1,x2;
            y1+=x;
            x1=y1-minn;
            y2+=x;
            x2=y2-maxx;
            printf("%d,%d are closest, %d,%d are most distant.\n",x1,y1,x2,y2);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值