给定两个整数L和U,你需要在闭区间[L,U]内找到距离最接近的两个相邻质数C1和C2(即C2-C1是最小的),如果存在相同距离的其他相邻质数对,则输出第一对。
同时,你还需要找到距离最远的两个相邻质数D1和D2(即D1-D2是最大的),如果存在相同距离的其他相邻质数对,则输出第一对。
输入格式
每行输入两个整数L和U,其中L和U的差值不会超过1000000。
输出格式
对于每个L和U ,输出一个结果,结果占一行。
结果包括距离最近的相邻质数对和距离最远的相邻质数对。(具体格式参照样例)
如果L和U之间不存在质数对,则输出“There are no adjacent primes.”。
数据范围
1≤L 输入样例:
2 17
14 17
输出样例:
2,3 are closest, 7,11 are most distant.
There are no adjacent primes.
解析:
不能暴力筛,因为n=2e9多的范围,肯定会超时。
假设一个合数x
一个因数 n 另一个 x/n
那么因数n一定小于 x/n
根据这个性质我们可以把[L,R]内的合数开根号筛出来。
2e9开根号大约50000
n=50000 我们跑线性筛。找出[1.50000]中的所有质因子。那么一个合数分解肯在有一部分在[1.50000]。
对于[1,50000]中每个质数p,将[L,R]中所有为p的倍数筛掉(至少为2倍)
那么大于等于L的最小的p的倍数 p0=(L+p-1)/p * p;
因为至少要是2倍 p0=max(2*p,(L+p-1)/p * p);
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+1000;
int prime[N],cnt;
bool st[N];
ll l,r;
void init(int n)
{
memset(st,false,sizeof st);
cnt=0;
for(int i=2;i<=n;i++)
{
if(!st[i]) prime[++cnt]=i;
for(int j=1;j<=cnt&&prime[j]<=n/i;j++)
{
st[prime[j]*i]=true;
if(i%prime[j]==0) break;
}
}
}
int main()
{
while(~scanf("%lld %lld",&l,&r))
{
init(50000);
memset(st,false,sizeof st);
for(int i=1;i<=cnt;i++)
{
ll p=prime[i];
for(ll j=max(p*2,(l+p-1)/p*p);j<=r;j+=p) st[j-l]=true;
}
cnt=0;
for(int i=0;i<=r-l;i++)
{
if(!st[i]&&(i+l)>=2) //1不是质数,所以必须从2开始
{
prime[++cnt]=i+l;
}
}
if(cnt<2) puts("There are no adjacent primes.");
else
{
int minp=1,maxp=1;
for(int i=1;i<=cnt-1;i++)
{
int d=prime[i+1]-prime[i];
if(d<prime[minp+1]-prime[minp]) minp=i;
if(d>prime[maxp+1]-prime[maxp]) maxp=i;
}
printf("%d,%d are closest, %d,%d are most distant.\n",prime[minp],prime[minp+1],prime[maxp],prime[maxp+1]);
}
}
}