基础数论(Prime Distance)(素数筛+离散化+合数性质)

Prime Distance

被称为数论的数学分支是关于数的性质的。数理论家几千年来一直感兴趣的领域之一是素数问题。素数是一个没有适当因子的数(它只能被1和它本身整除)。第一个素数是2,3,5,7,但是它们很快就变得不那么频繁了。其中一个有趣的问题是它们在不同的范围内有多密集。相邻素数是两个都是素数的数,但相邻素数之间没有其他素数。例如,2,3是唯一的相邻素数也是相邻的数。 你的程序有两个数字:L和U(1<=L < U<=2147483647),你要找到最接近的两个相邻素数C1和C2(L<=C1 < C2<=U)(即C2-C1是最小值)。如果有其他线对相距相同,则使用第一对线对。你还可以找到两个相邻的素数D1和D2(L<=D1 < D2<=U),其中D1和D2尽可能地彼此远离(如果有并列关系,再次选择第一对)。

Input

每行输入将包含两个正整数L和U,其中L < U。L和U之间的差值不超过1000000。

Output

对于每个L和U,输出要么是不存在相邻素数的语句(因为两个给定数字之间的素数少于两个),要么是给出两对相邻素数的行。

Sample Input

2 17
14 17

Sample Output

2,3 are closest, 7,11 are most distant.
There are no adjacent primes.

这个题大意就是说给一个区间,然后求出在这个区间内相邻质数距离最大和最小的那两对质数,另外要注意在题目中给出的范围(1<=L < U<=2147483647),2e9的范围,如果用线性筛的话时间空间都会超限,题目中还说了L和U之间的差值不超过1000000,所以说咱们要是暴力求的话很大一部分求出的素数是没用的,但是筛素数又一定是从头开始的,那咱们就可以想到一个性质了,
在这里插入图片描述
在这里插入图片描述
具体代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 1000010;
typedef long long LL;
int prime[N],cnt;
bool st[N];
void init(int n){//线性筛板子
	memset(st,0,sizeof st);
	cnt = 0;
	for(int i=2;i<n;i++){
		if(!st[i]) prime[cnt++] = i;
		for(int j=0;prime[j]*i<n;j++){
			st[i*prime[j]] = true;
			if(i % prime[j] == 0) break;
		}
	}
}
int main(){
	int l,r;
	while(cin>>l>>r){
		init(50000);//注意这个50000,因为50000^2比2^31-1大
		if(l == 1) l = 2;//因为l=1和l=2一样,所以我就感觉这样写的话会少一些麻烦
		if(r == 1) r = 2;
		memset(st,0,sizeof st);
		for(int i=0;i<cnt;i++){
			LL p = prime[i];//这个地方要开LL,因为如果p是int,j也是int,当j很大的时候他可能会爆int,因为这个j可能取到int的极限
			for(LL j=max(p*2,(l+p-1)/p*p);j<=r;j+=p){//注意这个max,他至少是从p的两倍开始筛的,还有这个(l+p-1)/p*p,他的原型是[l/p]*p,
			//就是从大于等于l的第一个p的倍数开始筛,有个公式可以推到代码所展现出来的,就是上取整和下取整之间的关系
				st[j-l] = true;//因为数组没有那么大,所以相当于一个离散化
			}
		}
		cnt = 0;
		for(int i=0;i<=r-l && i+l>=2;i++)
		if(!st[i]) prime[cnt++] = i+l;
		int minn = 0,maxn = 0;
		for(int i=0;i+1<cnt;i++){
			int d = prime[i+1] - prime[i];
			if(d < prime[minn+1] - prime[minn]) minn = i;
			if(d > prime[maxn+1] - prime[maxn]) maxn = i;
		}
		if(cnt<2) puts("There are no adjacent primes.");
		else printf("%d,%d are closest, %d,%d are most distant.\n",prime[minn],prime[minn+1],prime[maxn],prime[maxn+1]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇智波一打七~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值