题意
给定区间[l, r],长度小于1e6,l和r小于1e9,问这个区间中相邻两个素数差值的最大值和最小值。如果只有一个素数或者没有素数则输出There are no adjacent primes.
思路
模板题
因为每个合数x都有一个小于
x
\sqrt{x}
x的因子,所以只要筛出
[
2
,
r
]
[2, \sqrt{r}]
[2,r]之间的素数,然后枚举素数p,把这个区间中p的倍数全部筛掉即可。
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
const int N = 1000005;
std::vector<int> prime, pr;
bool isprime[N];
void init(int MAX) {
isprime[1] = true;
memset(isprime, false, sizeof(isprime));
prime.clear();
for (int i = 2; i < MAX; ++i) {
if (!isprime[i]) {
prime.push_back(i);
}
for (int j = 0; j < prime.size() && i * prime[j] < MAX; ++j) {
isprime[i * prime[j]] = true;
}
}
}
void getPrime(int l, int r) {
// init((int)ceil(sqrt(r)) + 2);
pr.clear();
memset(isprime, false, (r - l + 1) * sizeof false);
for (int j = 0; j < prime.size(); ++j) {
for (int i = std::max(2ll, (l - 1ll + prime[j]) / prime[j]); i <= r / prime[j]; ++i) {
isprime[i * prime[j] - l] = true;
}
}
for (int i = 0; i <= r - l; ++i) {
if (!isprime[i] && i + l != 1) pr.push_back(i + l);
}
}
int main() {
int l, r;
init(1 << 16);
while (~scanf("%d%d", &l, &r)) {
getPrime(l, r);
if (pr.size() < 2) {
printf("There are no adjacent primes.\n");
continue;
}
int mn = 1e9, mx = 0;
int pos1, pos2;
for (int i = 1; i < pr.size(); ++i) {
if (mn > pr[i] - pr[i - 1]) {
mn = pr[i] - pr[i - 1];
pos1 = i;
}
if (mx < pr[i] - pr[i - 1]) {
mx = pr[i] - pr[i - 1];
pos2 = i;
}
}
printf("%d,%d are closest, %d,%d are most distant.\n", pr[pos1 - 1], pr[pos1], pr[pos2 - 1], pr[pos2]);
}
return 0;
}