|
|
#include <bits/stdc++.h>
|
|
|
using namespace std;
|
|
|
typedef long long LL;
|
|
|
|
|
|
// 线性筛
|
|
|
const int N = 1e6 + 10;
|
|
|
int primes[N], cnt;
|
|
|
bool st[N];
|
|
|
void get_primes(int n) {
|
|
|
memset(primes, 0, sizeof primes);
|
|
|
memset(st, 0, sizeof st);
|
|
|
cnt = 0;
|
|
|
for (int i = 2; i <= n; i++) {
|
|
|
if (!st[i]) primes[cnt++] = i;
|
|
|
for (int j = 0; primes[j] * i <= n; j++) {
|
|
|
st[primes[j] * i] = true;
|
|
|
if (i % primes[j] == 0) break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool b[N]; // 记录区间内有哪些数是合数
|
|
|
int c[N], cl; // 区间内有哪些质数
|
|
|
int l, r; // 区间范围
|
|
|
|
|
|
int main() {
|
|
|
// 加快读入
|
|
|
ios::sync_with_stdio(false), cin.tie(0);
|
|
|
|
|
|
// 一次性筛质数
|
|
|
get_primes(50000);
|
|
|
|
|
|
while (cin >> l >> r) {
|
|
|
memset(b, 0, sizeof b); // 清除合数数组
|
|
|
memset(c, 0, sizeof c); // 清除质数数组
|
|
|
cl = 0;
|
|
|
|
|
|
// 标识质数的倍数,也就是合数有哪些
|
|
|
for (int i = 0; i < cnt; i++) {
|
|
|
LL p = primes[i];
|
|
|
for (LL j = max(p * 2, (l + p - 1) / p * p); j <= r; j += p) // 枚举p的2倍以上倍数,最小要比l大,最大不能超过r
|
|
|
b[j - l] = true; // 采用偏移量记录剔除标识
|
|
|
}
|
|
|
|
|
|
// Hack data: 1 100
|
|
|
// 输出: 1,2 are closest, 89,97 are most distant.
|
|
|
// 答案: 2,3 are closest, 89,97 are most distant.
|
|
|
// 原因: 下面的逻辑判断b[i]是否等于0,表示i+l不是某个质数的倍数(合数),也就是是合数,但这样判断是有问题的,因为考虑边界问题
|
|
|
// 1通过上面的代码是无法剔除掉的,也就是说,上面的剔除的是合数,但数字除了合数,可不是只有质数,还有一个特殊的数字1,1即不是质
|
|
|
// 数也不是合数,这句话可不是说说而已。
|
|
|
for (int i = 0; i <= r - l; i++)
|
|
|
if (!b[i] && i + l > 1) // 如果不是合数,并且,不是1,才是质数
|
|
|
c[++cl] = i + l; // 区间内的质数多了一个i+l质数
|
|
|
|
|
|
if (cl < 2)
|
|
|
puts("There are no adjacent primes.");
|
|
|
else {
|
|
|
int mi = 1, mx = 1; // 第一只猴子就是大王
|
|
|
for (int i = 1; i < cl; i++) { // 范围是1~cl,而此处因为要枚举的是每个当前i与后一个的关系,所以需要枚举到cl-1
|
|
|
int d = c[i + 1] - c[i];
|
|
|
if (d < c[mi + 1] - c[mi]) mi = i;
|
|
|
if (d > c[mx + 1] - c[mx]) mx = i;
|
|
|
}
|
|
|
printf("%d,%d are closest, %d,%d are most distant.\n", c[mi], c[mi + 1], c[mx], c[mx + 1]);
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
} |