质数距离
题目链接:ybt高效进阶6-2-2
题目大意
要你求 L~R 中最近的和最远的两对相邻的质数。
思路
发现
L
,
R
L,R
L,R 很大,但是
R
−
L
R-L
R−L 比较小,考虑从这里入手。
发现小到可以拿桶装着,考虑就求
R
−
L
R-L
R−L 之间的数是否是质数。
然后考虑你
R
\sqrt{R}
R 内的质数就可以把所有
1
∼
R
1\sim R
1∼R 的质数筛出。
那你就直接跑每个
R
\sqrt{R}
R 内的质数,然后跑它在
L
∼
R
L\sim R
L∼R 之间的非一倍倍数,跑到的数都不是质数。
然后有一个要特判的就是 1 1 1 不是质数,如果区间中有 1 1 1 一定要特判一下。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
ll l, r, prime[100001];
bool np[100001], lr[10000001];
ll maxn, minn, maxx, minx, lst;
void get_prime(ll n) {
for (ll i = 2; i <= n; i++) {
if (!np[i]) prime[++prime[0]] = i;
for (ll j = 1; j <= prime[0] && 1ll * i * prime[j] <= n; j++) {
np[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
int main() {
get_prime(sqrt(2147483647));
while (scanf("%lld %lld", &l, &r) != EOF) {
ll rr = sqrt(r);
for (ll i = 1; i <= prime[0] && prime[i] <= rr; i++) {
ll now = l / prime[i] * prime[i];
if (now < l) now += prime[i];
if (now == prime[i]) now += prime[i];
while (now <= r) {
lr[now - l] = 1;
now += prime[i];
}
}
if (1 - l >= 0) lr[1 - l] = 1;
minn = 3e9;
maxn = -3e9;
lst = -1;
for (ll i = l; i <= r; i++) {
if (!lr[i - l]) {
if (lst == -1) {
lst = i;
continue;
}
if (minn > i - lst) {
minn = i - lst; minx = i;
}
if (maxn < i - lst) {
maxn = i - lst; maxx = i;
}
lst = i;
}
lr[i - l] = 0;
}
if (minn == 3e9) printf("There are no adjacent primes.\n");
else printf("%lld,%lld are closest, %lld,%lld are most distant.\n", minx - minn, minx, maxx - maxn, maxx);
}
return 0;
}