题目链接
知识点:质数筛、优化
题意
求 l l l到 r r r区间内所有的质数中相邻质数之差绝对值最大和最小值,并输出答案相同时质数小的质数
思路
1
到
2
31
的
质
数
筛
M
L
E
,
注
意
到
区
间
长
度
不
超
过
1
6
1到2^{31}的质数筛MLE,注意到区间长度不超过1^6
1到231的质数筛MLE,注意到区间长度不超过16
预
处
理
出
不
超
过
2
31
的
质
数
筛
,
然
后
用
这
些
质
数
推
出
l
到
r
范
围
内
的
质
数
预处理出不超过\sqrt{2^{31}}的质数筛,然后用这些质数推出l到r范围内的质数
预处理出不超过231的质数筛,然后用这些质数推出l到r范围内的质数
存
储
l
到
r
范
围
内
的
质
数
把
l
的
下
标
设
为
0
,
r
的
下
标
为
r
−
l
存储l到r范围内的质数把l的下标设为0,r的下标为r-l
存储l到r范围内的质数把l的下标设为0,r的下标为r−l
实现思路见代码。
代码
#include"cstdio"
#include"vector"
#include"bitset"
#include"algorithm"
#define ll long long
#define vec vector<ll>
#define pb push_back
#define all(a) (a).begin(),(a).end()
const ll N=2e5+10,M=1e6+10;
using namespace std;
vec preprime;//sqrt(1<<31)范围内的质数
bitset<M> notprime;
vec prime,dis;//prime:l到r的质数,dis:l到r的质数中相邻质数的距离
//预处理sqrt(1<<31)范围内的质数
void getprime() {
for(ll i=2; i<N; i++) {
if(!notprime[i]) preprime.pb(i);
for(ll j=0; j<preprime.size()&&i*preprime[j]<N; j++) {
notprime[i*preprime[j]]=true;
if(i%preprime[j]==0) break;
}
}
}
int main() {
ll l,r;
getprime();
while(~scanf("%lld%lld",&l,&r)) {
prime.resize(0);
notprime.reset();
if(l==1) notprime[0]=true;//区间包含1,1不是质数
//枚举sqrt(1<<31)范围内的质数,preprime[i]*preprime[i]解释见for内的注释,
//preprime[i]*preprime[i]>r时更大的质数没有贡献
for(int i=0; i<preprime.size()&&preprime[i]*preprime[i]<=r; i++) {
//枚举第i个质数的j倍;对于小于preprime[i]的倍数,交换质数和倍数的含义,
//发现之前已经枚举过了;(l-1)/preprime[i]+1 是 l/preprime[i] 的向上取整,
//最小的倍数;r/preprime[i]:最大的倍数
for(int j=max(preprime[i],(l-1)/preprime[i]+1); j<=r/preprime[i]; j++) {
notprime[j*preprime[i]-l]=true;
}
}
//筛出l到r的质数
for(int i=0; i<=r-l; i++) {
if(!notprime[i]) {
prime.pb(i+l);//记得还原
}
}
if(prime.size()<2) {
printf("There are no adjacent primes.\n");
continue;
}
dis.resize(prime.size()-1);
//计算距离
for(int i=0; i<prime.size()-1; i++) dis[i]=prime[i+1]-prime[i];
ll minans=dis[0],maxans=dis[0];
ll minindex,maxindex;
minindex=maxindex=0;
for(int i=0; i<dis.size(); i++) {
if(dis[i]<minans) {
minans=dis[minindex=i];
}
if(dis[i]>maxans) {
maxans=dis[maxindex=i];
}
}
printf("%lld,%lld are closest, %lld,%lld are most distant.\n",
prime[minindex],prime[minindex+1],prime[maxindex],prime[maxindex+1]);
}
return 0;
}