题目地址
可以通过 R-L来寻找突破口, 对于任何一个合数都有不超过sqrt(n)的因子,所以我们可以筛出2~sqrt®的质数再通过这些质数将L-R中的所有非质数标记。最后直接枚举。
对于筛选出来的每一个质数p,它对应L-R区间的倍数为j*p(ceil(L/p) <= j <= R/p)
详细见代码
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define int long long
#define sc scanf
#define pf printf
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long LL;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 1e9+7;
const int N = 1000010;
int primes[N],pos,l,r,cnt;
bool book[N],book1[N];
signed main(){
IOS;
#ifdef ddgo
freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
#endif
for(int i=2;i<=50000;i++)//筛质数,50000是根据题目的范围求得
if(!book[i]){
primes[cnt++] = i;
for(int j=i;j*i<=50000;j++) book[i*j] = true;
}
while(cin>>l>>r){
memset(book1,false,sizeof(book1));
if(l == 1) book1[0] = true;//特判一下1
for(int i=0;i<cnt&&primes[i]<r;i++){//根据质数将书友L-R的非质数标记
int p = primes[i];
for(int j=max(2ll,(l+p-1)/p);j<=r/p;j++) //这里j不能为1倍
book1[p*j-l] = true;
}
int ma = -INF,mi = INF,x=-1;
int mi_l=0,mi_r=0,ma_l=0,ma_r=0;//循环找出答案
for(int i=0;i<=r-l;i++){
if(book1[i]) continue;
if(x == -1) x = i;
else{
if(i-x < mi){
mi = i-x;
mi_l = x+l;
mi_r = i+l;
}
if(i-x > ma){
ma = i-x;
ma_l = x+l;
ma_r = i+l;
}
x = i;
}
}
if(ma == -INF || mi == INF) cout<<"There are no adjacent primes."<<endl;
else cout<<mi_l<<","<<mi_r<<" are closest, "<<ma_l<<","<<ma_r<<" are most distant."<<endl;
}
return 0;
}