#数论,线性筛,eratosthenes#poj 2689 Prime Distance

本文介绍了一种高效算法,用于在指定区间内寻找差值最大和最小的相邻质数对。通过试除法和线性筛算法,实现了对大量数字的快速筛选,确保了算法的时间效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

在一个区间[l...r][l...r][l...r],求两对相邻的质数,一对差值最大,一对最小(可以相同)(1≤l≤r≤2147483648(unsigned))(1\leq l\leq r\leq 2147483648(unsigned))(1lr2147483648(unsigned))


分析

然而直接跑绝对会TLE,但是可以用试除法的思想可以发现可以跑2到r\sqrt rr筛一筛(我选离线),然后每次询问筛一筛,就没有什么了,时间复杂度O(47000+(r−l)log⁡log⁡(r−l))O(47000+(r-l)\log \log(r-l))O(47000+(rl)loglog(rl))


代码

#include <cstdio>
#include <bitset>
typedef unsigned uit;
uit prime[4793],v[46341],m,l,r;
int main(){
	for (register uit i=2;i<=46340;i++){//线性筛
		if (!v[i]) v[i]=i,prime[++m]=i;
		for (register uit j=1;j<=m;j++){
			if (prime[j]>v[i]||prime[j]>46340/i) break;
			v[i*prime[j]]=prime[j];
		}
    }
	while (scanf("%u%u",&l,&r)==2){//unsigned
		if (l==1) l=2; if (r==1) r=2;
	    std::bitset<1000010>v1; v1.reset();
		for (register uit j=1;j<=m;j++)
		for (register uit k=l/prime[j];k<=r/prime[j];k++)
		if (prime[j]*k>=l&&prime[j]*k<=r&&k>1) v1[prime[j]*k-l]=1; //欧式筛
		uit pri2=l,pri1,ans1=0,ans2=r-l<<1,a1,a2,b1,b2;
		while (v1[pri2-l]&&pri2<=r) pri2++;//找到较小的质数
		for (register uit j=pri2;j<=r;j=pri1){
			pri1=j+1;
			while (v1[pri1-l]&&pri1<=r) pri1++;//找较大的质数
			if (pri1<=r&&pri2<=r&&!v1[pri1-l]&&!v1[pri2-l]){
				if (ans1<pri1-pri2) ans1=pri1-pri2,a1=pri2,a2=pri1;
				if (ans2>pri1-pri2) ans2=pri1-pri2,b1=pri2,b2=pri1;
			}
			pri2=pri1;//更新较小的质数
		}
		if (!ans1) printf("There are no adjacent primes.\n");//不存在答案
		else printf("%d,%d are closest, %d,%d are most distant.\n",b1,b2,a1,a2);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值