题目链接:--->....<---
题意:
给定两个整数L,R(1<=L<=R<=2^31},R-L<=10^6)L,R(1<=L<=R<=2^31,R−L<=10^6),求闭区间 【l,R]中相邻两个质数的差的最小值和最大值是多少,分别输出这两个质数。
【输入格式】
输入有若干行,每行两个整数 L,RL,R
【输出格式】
对于每个L,RL,R,输出最小值和最大值,格式参照样例。若区间内无质数,输出"There are no adjacent primes."。
思路:考虑L和R特别大,R-L特别小,所以这道题的突破口一定在R-L,我们可以“埃氏筛”或者“线性筛”筛取[1,sqrt(R)]之间的质数,然后暴力去标记[l,r]之间质数的倍数,可以证明,枚举质数到sqrt(R),可以将[1,R]中的非质数全部标记,但是需要将 [l,r] 离散成 [0,r-l] 。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<cmath>
#include<algorithm>
#define R register
#define ll long long int
using namespace std;
const int N=4e6+5;
ll Min=1e16,Max=-1e16;
ll l,r,num,pos,flag[N],prime[N],notprime[N];
ll ans1[3],ans2[3],ans;
inline void init(){
memset(flag,0,sizeof(flag));num=0;
memset(ans1,0,sizeof(ans1));ans=0;
memset(ans2,0,sizeof(ans2));
Min=1e16;Max=-1e16;pos=0;
memset(prime,0,sizeof(prime));
memset(notprime,0,sizeof(notprime));
}
inline void update(){
notprime[1]=1;
for(R int i=2;i<=sqrt(r)+1;++i){
if(!notprime[i]){
prime[++num]=i;
for(R int j=i;j<=(sqrt(r)+1)/i;++j)
notprime[i*j]=1;
}
}
}
inline void query(){//判断素数, 求距离
if(l==1)
flag[0]=1;
for(R int i=1;i<=num;++i){
//printf("%lld %lld
",l/prime[i],r/prime[i]);
for(R int j=l/prime[i];j<=r/prime[i];j++)
if(j>=2&&prime[i]*j>=l)
flag[prime[i]*j-l]=1;
}
R ll last=-1;
for(R ll i=0;i<=r-l;++i){
if(!flag[i]){
if(last==-1)
last=i;
else
{
ans=1;
if(i-last<Min){
ans1[1]=last+l;
ans1[2]=i+l;
Min=i-last;
}
if(i-last>Max){
ans2[1]=last+l;
ans2[2]=i+l;
Max=i-last;
}
last=i;
}
}
}
}
int main(){
while(cin>>l>>r){
init();
update();
query();
if(ans)
printf("%lld,%lld are closest, %lld,%lld are most distant.
",ans1[1],ans1[2],ans2[1],ans2[2]);
else printf("There are no adjacent primes.
");
}
return 0;
}