题意:给一个区间l到r,问在l和r之间的相邻素数间隔最大的和间隔最小的分别是哪两对。
思路:由于这题的数据比较大,所以不能每次直接用筛法把区间里的素数都求出来,也不能把int里的所有素数都打表,所以只能想别的办法。
我们先把1<<16以内的素数都求出来,大概有50000个左右,因为int以内的数,只要它不是素数,一定可以被1<<16以内的素数整除,所以我们只要把用筛法把题目给定区间里的所有非素数筛掉,剩下的就是素数了,再遍历一遍,找到间隔最小和最大的相邻素数对就可以了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const int maxn=1000010;
int n,num;
bool vis[maxn],ans[maxn];
int prime[maxn],prm[maxn];
void getprime(){
prm[n++]=2;
for(int i=3;i<=(1<<16);i+=2){
if(!vis[i]){
prm[n++]=i;
for(int j=2*i;j<=(1<<16);j+=i)
vis[j]=1;
}
}
}
int main()
{
getprime();
long long l,u;
while(cin>>l>>u){
num=0;
memset(ans,0,sizeof(ans));
for(int i=0;i<n&&prm[i]*prm[i]<=u;i++){
long long temp = (l + prm[i] - 1) / prm[i] * prm[i];
if (temp == prm[i])
temp += prm[i];
while (temp <= u)
{
ans[temp - l] = 1;
temp += prm[i];
}
}
if(l==1)
ans[0]=1;
for(int i=l;i<=u;i++)
if(ans[i-l]==0)
prime[num++]=i;
// for(int i=0;i<num;i++)
// cout<<prime[i]<<endl;
if(num<2)
cout<<"There are no adjacent primes."<<endl;
else{
int maxc=0;
int minc=1e9;
int ans1,ans2;
for(int i=0;i<num-1;i++){
int xx=prime[i+1]-prime[i];
if(xx>maxc){
maxc=xx;
ans2=i;
}
if(xx<minc){
minc=xx;
ans1=i;
}
}
printf("%d,%d are closest, %d,%d are most distant.\n",prime[ans1],prime[ans1+1],prime[ans2],prime[ans2+1]);
}
}
}