0x31 prime distance

正好学校的c语言也有线性筛欧拉函数的题,可以复习一下数论

https://www.acwing.com/problem/content/description/198/

给定两个整数l,r,求闭区间 [l,r] 中相邻两个质数的差的最大值和最小值

由于l,r的数据范围较大(<=\(2^{31}\))所以这题用一次筛法都会寄

所以我们考虑二次筛法:先筛出一个较小范围内的质数,然后遍历筛出的质数去筛区间中的合数

区间中的合数可以被筛掉需要我们第一次筛法筛到最大数据范围的平方根,就是\(2^{15}\)≈50000

二次筛法如何筛:

求出 [l,r]中最小的p的倍数:\([\frac{l}{p}]*p\) : ceil( (double) L / p) * p
或者\([\frac{l+p-1}{p}]*p\)

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=100000;
const int N=1000010;
bool st[N];int m;
int  v[maxn],prime[maxn];
void primes(ll n){
	memset(v,0,sizeof v);
	m=0;
	for(int i=2;i<=n;i++){
		if(v[i]==0){
			v[i]=i;prime[m++]=i;
		}
		for(int j=1;j<m;j++){
			if(prime[j]>v[i]||prime[j]*i>n)break;
			v[i*prime[j]]=prime[j];
		}
	}
}//线性筛
int main(){
ll l,r;
while(cin>>l>>r){
memset(st,0,sizeof st);
primes(50000);
for(int i=0;i<m;i++){
	ll p=prime[i];
	for(ll j=max(2*p,(l+p-1)/p*p);j<=r;j+=p)st[j-l]=1;
}
m=0;
for(int i=0;i<=r-l;i++){
	if(!st[i]&&i+l>1)prime[m++]=i+l;
}
if(m<2)printf("There are no adjacent primes.\n");
else{
	int minn=0,maxx=0;
	for(int i=0;i<m-1;i++){
		int d=prime[i+1]-prime[i];
		if(d<prime[minn+1]-prime[minn])minn=i;
		if(d>prime[maxx+1]-prime[maxx])maxx=i;
	}
	printf("%d,%d are closest, %d,%d are most distant.\n",prime[minn],prime[minn+1],prime[maxx],prime[maxx+1]);
	
}
}return 0;
}



posted @ 2022-03-22 08:41  misasteria  阅读(25)  评论(0编辑  收藏  举报