0902-区间素数筛-POJ 2689 Prime Distance

版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/82316772

传送门

大致题意

给定 L, R,保证 L, R在int范围以内, R − L ≤ 10^6 ,问 [L, R] 中距离最近的两个相邻质数,和距离最远的两个相邻质数。区间内若没有相邻的质数则输出:There are no adjacent primes.

分析

这个范围告诉我们任何一种我们熟知的求素数的方法都会TLE(except Miller_Rabin),那我们就来两次素数筛

先筛出\sqrt{R}以内的所有素数,然后再用这些素数去筛 L 到 R 这个区间的素数,就搞定啦

不过这道题有个坑点,一不小心就会RE,我就这样卡死了,不过在dzy的帮助下还是解决了,%%%%感谢DZYO大佬的帮助%%%%

先来组数据,大家感受一下:2146483648 2147483647

等会儿我会在程序中指出问题所在

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include <assert.h>
#define N 50000
using namespace std;
int l,r,pri[N+10],num=0,p[1000009],hh[1000009];
bool mark[N+10];
void prime(){//我用的是线性筛,进行第一次筛 
	mark[1]=1;
	for(int i=2;i<=N;++i){
		if(!mark[i]) pri[++num]=i;
		for(int j=1;j<=num&&pri[j]*i<=N;++j){
			mark[pri[j]*i]=1;
			if(i%pri[j]==0) break;
		}
	}
}
int main(){
	prime();
	while(scanf("%d%d",&l,&r)!=EOF){
		memset(p,0,sizeof(p));//每次都要清空 
		if(l==1) l=2;//反正1也没用,而且会干扰后面的答案,所以我们直接忽略 
		int i,j,k=sqrt(r)+1;
		for(i=2;i<=k;++i){
			if(!mark[i]){
				int down=l/i;
				if(down<=1) down=2;
				for(j=down;1ll*j*i<=r;++j)	p[1ll*j*i-l]=1;
			}
		} 
		int tot=0,minn=(1ll<<31)-1,a1,a2,maxn=-1,b1,b2;
		for(long long i=l;i<=r;++i)	if(!p[i-l]) hh[++tot]=i;//就是这个地方,如果r恰好取到int的最大值时,再i++一次,i就爆了;
		if(tot<=1) printf("There are no adjacent primes.\n");
		else{
			for(i=2;i<=tot;++i){
				int dis=hh[i]-hh[i-1];
				if(dis<minn){minn=dis;a1=hh[i-1];a2=hh[i];}
				if(dis>maxn){maxn=dis;b1=hh[i-1];b2=hh[i];}
			}
			printf("%d,%d are closest, %d,%d are most distant.\n",a1,a2,b1,b2);
		}
	}
	return 0;
}

最后来一句:

如果有多组数据的,一定要考虑清空,初始化

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/82316772
今日推荐