整数分解与筛法 Prime Distance

题目描述

原题来自:Waterloo local,题面详见 POJ 2689

给定两个整数 L,R,求闭区间 [L,R]中相邻两个质数差值最小的数对与差值最大的数对。当存在多个时,输出靠前的素数对。

输入格式

多组数据。每行两个数 L,R。

输出格式

详见输出样例。

样例

Input复制 Output复制
2 17 2,3 are closest, 7,11 are most distant.
14 17 There are no adjacent primes.

数据范围与提示

对于全部数据,1≤L<R<231,*R*−*L*≤106。

算法分析

注意到L和R的范围很大,但R-L却不大,所以可以得出以下思路:

  1. 预处理出1~sqrt(2^31-1)范围内的质数。
  2. 对输入的每一对L和R,用预处理求出的小质数去标记L到R范围内的合数,没标记的就是质数。
  3. 把没标记的质数放入数组中,求出相邻两数的差的最小值和最大值。
  4. 按题目要求输出即可。
#include<bits/stdc++.h>
using namespace std;
long long l,r;
long long len;
vector<long long> v;
bool vis[2000005];
vector<long long> v1;
void zs(){
	bool t[56345];
	memset(t,0,sizeof(t));
    for(long long i = 2; i*i<=INT_MAX; i++){
        if(t[i]==0){
            v.push_back(i);
            for(long long j = i+i; j*j<=INT_MAX; j+=i){
                t[j] = 1;
            }
        }
    }
}
void bj(){
	memset(vis,0,sizeof(vis));
	long long t = l;
	for(long long i = 0; i<len; i++){
		if(l%v[i]!=0){
			l = l+(v[i]-l%v[i]);
		}
		for(long long j = max(l,v[i]+v[i]); j<=r; j+=v[i]){
			vis[j-t] = 1;
		}
		l = t;
	}
}
int main(){
	zs();
	len = v.size();
	while(cin>>l>>r){
		long long mn = LONG_LONG_MAX;
		long long mx = 0;
		int pn = 0;
		int px = 0;
		bj();
		for(int i = l; i<=r; i++){
			if(vis[i-l]==0 && i!=1){
				v1.push_back(i);
			}
		}
		for(int i = 0; i<v1.size()-1; i++){
			if(v1[i+1]-v1[i]<mn){
				mn = v1[i+1]-v1[i];
				pn = i;
			}
			if(v1[i+1]-v1[i]>mx){
				mx = v1[i+1]-v1[i];
				px = i;
			}
		}
		if(v1.size()<=1){
			printf("There are no adjacent primes.\n");
		}else{
			printf("%lld,%lld are closest, %lld,%lld are most distant.\n",v1[pn],v1[pn+1],v1[px],v1[px+1]);
		}
		v1.clear();
	}
	return 0;
}
posted @ 2026-06-14 11:58  xmgene  阅读(9)  评论(0)    收藏  举报