码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-07-05 12:32:01      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:poj   数论   素数   

题意:给定两个数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;
	}
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:poj   数论   素数   

原文地址:http://blog.csdn.net/ac_0_summer/article/details/46761789

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!