题解 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."。


整理步骤

  1. 预处理int范围内的所有质数。
  2. 标记\([l,r]\)范围内的合数。
  3. 整理区间内未被标记的质数,同时更新答案。
  4. 输出答案

参考程序:

#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);
	}
}
posted @ 2020-10-18 10:30  Sure042  阅读(281)  评论(0编辑  收藏  举报