题解 UVA10140 Prime Distance
题解 UVA10140 Prime Distance
我很弱 写不出很高级的题解。
所以来写一个简单好懂的思路!
思路
题目中所给范围为\(1≤l≤r≤2^{31}\),不算很大,所以我们可以利用线性筛处理出int范围内的所有质数,然后处理区间\([l,r]\)内为已知质数的整数(大于等于一)倍的数,标记这个合数(例:设\(x\)为一个质数,\(y=k \times x\)(\(k\)为大于等于1的整数)且\(l<=y<=r\),则标记\(y\)为合数),最后整理区间\([l,r]\)中出未被标记的数,同时判断相邻的质数之差是否为当前最小/最大值,若满足差最小/最大,则更新答案。
Tips:在整理区间内未被标记的数的过程中,记录所整理出的质数的数量,若质数数量小于等于1,则直接输出"There are no adjacent primes."。
整理步骤
- 预处理int范围内的所有质数。
- 标记\([l,r]\)范围内的合数。
- 整理区间内未被标记的质数,同时更新答案。
- 输出答案
参考程序:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
const int N=1e6+7;
ll l,r,total;
ll mx1,mx2,mn1,mn2,dismx,dismn=1e7+7;
ll c[N],prime[N],ym[N];
bool v[N],lym[N];
inline void Prime(ll n)//筛
{
for(re ll i=2;i<=n;i++)
{
if(!v[i])
prime[++total]=i;
for(re ll j=1;prime[j]*i<=n&&j<=total;j++)
{
v[i*prime[j]]=1;
if(!(i%prime[j])) break;
}
}
}
inline void comp(ll x,ll y)//更新答案
{
ll dis=x-y;
if(dis>dismx)//若相邻的两个质数差大于当前最大值
{
dismx=dis;//更新当前最大值,记录这两个质数
mx1=y;
mx2=x;
}
if(dis<dismn)//若相邻的两个质数小于当前最小值
{
dismn=dis;//更新当前最小值,记录这两个质数
mn1=y;
mn2=x;
}
return ;
}
int main()
{
Prime(5e4+7);//处理int范围内的所有质数
while(cin>>l>>r)//多组数据
{
memset(lym,0,sizeof(lym));//初始化
dismx=ym[0]=0;
dismn=1e7+7;//每次的最小值为一个非常大的值,保证大于1e6
if(l==1) l=2;
for(re ll i=1;i<=total;i++)//枚举每一个质数
{
for(re ll j=l/prime[i];j*prime[i]<=r;j++)//标记倍数
{
if(j<=1) j=2;
int am=prime[i]*j;
if(am<l||am>r) continue;//防止超范围
lym[am-l]=1;
}
}
for(re ll i=l;i<=r;i++)
if(!lym[i-l])
{
ym[++ym[0]]=i;//ym[0]存放质数个数
if(ym[0]>1)//若已处理出两个质数,则进行判断
comp(ym[ym[0]],ym[ym[0]-1]);
}
if(ym[0]<=1)//若质数个数小于等于1,输出
{
cout<<"There are no adjacent primes."<<endl;
continue;
}
printf("%lld,%lld are closest, %lld,%lld are most distant.\n",mn1,mn2,mx1,mx2);
}
}