1. 程式人生 > 其它 >0x31 prime distance

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;
}