!POJ 2689 Prime Distance-卡时间-(素数筛法)

题意:给定两个数l,r求这之间最近和最远的两个素数。数据范围是整数的上限。r-l<=10^6

分析:总思路是把l和r间的素数全部找出来,然后遍历一遍求最小距离和最大距离。用一个函数预处理数据范围内的所有素数是不现实的,一来数组不可r能开那么大二来会超时。想想素数筛的思想:用sqrt(n)以内的素数筛掉n以内的所有合数,剩下n以内的素数。这里既然预处理不可能,我们一样可以用sqrt(n)以内的素数来筛,只是这时这些素数预处理,然后每次输入l和r的时候用预处理的素数筛掉l和r之间的合数,剩下素数。sqrt(n)为2^16,也就是65536不会超时。

关键在于l,r之间的素数筛。还是用vis[]数组来做。直接用两个循环遍历 l~r 和 prim[] 估算一下应该是会超时的,所以用到一点优化技巧就是遍历l~r的时候每次加prim[i],而不是加1

代码:

#include<iostream>
#include<cstring>
using namespace std;
long long l,r,vis[5000003],l1,l2,r1,r2,init;
int prim[500005],mi,mx,cnt;
void is_prim()
{
	memset(vis,1,sizeof(vis));
	cnt=0;
	for(int i=2;i<=50000;i++){
		if(vis[i]){
			prim[cnt++]=i;
			for(int j=2;j*i<=50000;j++) vis[j*i]=0;
		}
	}
}
int main()
{
	is_prim();
	while(cin>>l>>r){
		for(int i=0;i<r-l+1;i++) vis[i]=1;
		if(l==1) vis[0]=0;
		for(int i=0;i<cnt&&prim[i]*prim[i]<=r;i++){
			for(long long j=(long long)max((long long)(prim[i]<<1),(l+prim[i]-1)/prim[i]*prim[i]);j<=r;j+=prim[i])
			   vis[j-l]=0;
		}
	    init=-1;
		mx=-1,mi=10000000;
		for(int i=0;i<r-l+1;i++){
			if(vis[i]){
				if(init!=-1){
					if(mi>i-init){
						mi=i-init;
						l1=init+l;
						r1=i+l;
					}
					if(mx<i-init){
						mx=i-init;
						l2=init+l;
						r2=i+l;
					}
				}
				init=i;
			}
		}
		if(mx==-1) cout<<"There are no adjacent primes."<<endl;
		else cout<<l1<<","<<r1<<" are closest, "<<l2<<","<<r2<<" are most distant."<<endl;
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值