france

https://github.com/francecil

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Prime Distance

Time Limit: 2 Seconds      Memory Limit: 65536 KB

The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number theoreticians for thousands of years is the question of primality. A prime number is a number that is has no proper factors (it is only evenly divisible by 1 and itself). The first prime numbers are 2,3,5,7 but they quickly become less frequent. One of the interesting questions is how dense they are in various ranges. Adjacent primes are two numbers that are both primes, but there are no other prime numbers between the adjacent primes. For example, 2,3 are the only adjacent primes that are also adjacent numbers.

Your program is given 2 numbers: L and U (1 <= L < U <= 2,147,483,647), and you are to find the two adjacent primes C1 and C2 (L <= C1 < C2 <= U) that are closest (i.e. C2-C1 is the minimum). If there are other pairs that are the same distance apart, use the first pair. You are also to find the two adjacent primes D1 and D2 (L <= D1 < D2 <= U) where D1 and D2 are as distant from each other as possible (again choosing the first pair if there is a tie).


Input

Each line of input will contain two positive integers, L and U, with L < U. The difference between L and U will not exceed 1,000,000.


Output

For each L and U, the output will either be the statement that there are no adjacent primes (because there are less than two primes between the two given numbers) or a line giving the two pairs of adjacent primes.


Sample Input

2 17
14 17


Sample Output

2,3 are closest, 7,11 are most distant.
There are no adjacent primes.


题目大意

求两个数之间相邻素数值相差最小和最大的数

分析:这道题是学习素数筛法的经典,应用到了区间筛素数。具体思路是先筛出1到sqrt(2147483647)之间的所有素数,然后再通过已经晒好素数筛出给定区间的素数。

题目中的U,L最大值可为整型上限,用纯粹的暴力筛法肯定要超时?怎么办,用二次筛法。U和L之间的合数,质因子不超过O(L^0.5),于是用筛法选出50000内的素数即可,因为50000的平方大于整形上线了。再用这些素数去筛出U-L之间的合数,剩下的就是U-L之间的素数了,边筛边计算两个素数之间的差,就OK了。另外,尤其小心的是U为1的情况,做素数题往往1是个坑爹的东西。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int N=50000;//为什么用到5W?U和L之间的合数,
//质因子不超过O(L^0.5),于是用筛法选出50000内的素数即可,因为50000的平方大于整形上线了
//比如说你只求到1W,但是你有个质数是42347(乱说一个的);那么42347*42347这个数你就不能使他为合数了
//因为你利用的是质数的倍数为合数的筛选法,你没筛选到50000这里
int r[1000000],a[N+100],b[N+100],z;

int main()
{
	int a0,b0,i,j;
	z=0;
	memset(a,0,sizeof(a));
	for(i=2;i<=N;i++)	//1st prime sieve第一次筛选得到5W内的所有质数
		if(a[i]==0){
			b[++z]=i;//b[z]用来得到a[]中所有的素数z:1->z
			for(j=2;i*j<=N;j++) a[i*j]=1;//i的倍数都为1
		}
	while(~scanf("%d%d",&a0,&b0)){
		memset(r,0,sizeof(r));
		int t=0,dis,max=-1,min=9999999,m1,m2;
		
		for(i=1;i<=z;i++){	//prime sieve again(b[1]到b[z]的素数)
			if(b[i]>b0)break;//对于一些小数据来说可以直接就中断掉了
			int s,t;
			s=(a0-1)/b[i]+1;//if(a0%b[i]==0)a0/b[i]==(a0-1)/b[i]+1;往上取整
			t=b0/b[i];//往下取整 这样取整的目的是为了让0<=j*b[i]-a0<=b0-a0 不然其他取整会超出范围
			for(j=s;j<=t;j++)//j的取值一定是>=1 如果是==1的情况 说明(a0-1)<b[i]即a0<=b[i]
				if(j>1) r[j*b[i]-a0]=1;//r[]==1表示为合数(为了限定范围在0<->(b0-a0),其实意思是j*b[i]是一个合数)
		}//j!=1 举 1,20 b[i]=7 这时s=1,t=2 if(j==1)可以 则[1*7-1]=1 正如上面所说后面还要a0=1 难道说7是合数?
			//总的来说,j==1时 b[i]是质数 j*b[i]-a0+a0肯定也是质数


		int k=-1;
		for(i=0;i<=b0-a0;i++)
			if(!r[i]){//如果r[i]==0 (不是合数的情况)
				if(k!=-1){//第一个是不能计的至少要两个
				dis=i-k;//与前一次的差
				if(dis>max){
					max=dis;
					m1=i+a0;//m1表示的是最大值
					}
					if(dis<min){
						min=dis;
						m2=i+a0;//m2表示的是第二小
					}
				
				
				}
				if(i+a0!=1) k=i;//第一次是这个用来下一次的使用
			//	k=i;//这样是错的 注意当a0=1的时候r[0]是一定为0的但是[举[1,2]]
			//如果这边没注意让 k=0的话,max=i-0,mi=i+a0(1);显然当元素中只有一个素数的时候是不能输出结果 但是这样却有结果				
			}

//if(max<0)说明没有进行过任何比较
		if(max<0) printf("There are no adjacent primes.\n");
		else printf("%d,%d are closest, %d,%d are most distant.\n",m2-min,m2,m1-max,m1);
	}
	return 0;
}
  



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

posted on 2014-07-24 00:17  france  阅读(310)  评论(0编辑  收藏  举报