题目描述:
给定两个整数L, R(1 ≤ L ≤ R ≤ 2 31 2^{31} 231, R - L ≤ 1 0 6 10^6 106),求闭区间 [L, R] 中相邻两个质数差最大和最小为多少。
题解:
因为范围太大,就算欧拉筛也会TLE,但是区间范围比较小,又因为一个合数N,至少能被2到根号N的一个数整除,2到根号N的素数一定是区间[L, R]内合数的质因子,所以可以先筛出2到5e4(
2
31
2^{31}
231开方)的素数,然后让这些素数筛去区间 [L, R] 的合数,最后留下的就是素数。
本题有几个细节:(1)当L为1时,要将L赋值为2,因为L = 1没有意义(1不是素数),并且如果L = 1会导致数组
a
a
a (数组
a
a
a是筛后区间中的素数)中会包括1,这明显是不对的;(2) 当a = 1时,表示prime[i] > L,此时prime[i]可能在区间 [L, R] 中,所以如果 a 仍然从1开始的话会导致 done[1 * prime[i]]被标记,即prime[i]被标记为合数,这显然是不对的,所以当a = 1时,a 应该从2开始。
AC代码:
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
// #include <unordered_set>
// #include <unordered_map>
#include <deque>
#include <list>
#include <iomanip>
#include <algorithm>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
//#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
//cout << fixed << setprecision(2);
//cout << setw(2);
const int N = 5e4 + 6, M = 1e9 + 7;
bool vis[N];
int prime[N];
int done[1000005];
int main() {
//freopen("/Users/xumingfei/Desktop/ACM/test.txt", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n = 5e4, cnt = 0;
for (int i = 2; i <= n; i++) {
if (vis[i] == 0)
prime[cnt++] = i;
for (int j = 0; j < cnt && prime[j] * i <= n; j++) {
vis[prime[j] * i] = 1;
if (i % prime[j] == 0) break;
}
}
int l, r;
while (cin >> l >> r) {
memset(done, 0, sizeof(done));
for (int i = 0; i < cnt; i++) {
if (l == 1) l = 2;
int a = (l - 1) / prime[i] + 1;
int b = r / prime[i];
if (a == 1) a = 2;
for (int j = a; j <= b; j++) {
done[prime[i] * j - l] = 1;
}
}
vector<int> a;
for (int i = 0; i <= r - l; i++) {
if (done[i] == 0) a.push_back(i + l);
}
int size = (int) a.size(), mx = -1, mn = 1e9, l1, r1, l2, r2;
for (int i = 1; i < size; i++) {
if (a[i] - a[i - 1] > mx) {
mx = a[i] - a[i - 1];
l1 = a[i - 1], r1 = a[i];
}
if (a[i] - a[i - 1] < mn) {
mn = a[i] - a[i - 1];
l2 = a[i - 1], r2 = a[i];
}
}
if (mx == -1) {
cout << "There are no adjacent primes." << '\n';
} else {
cout << l2 << "," << r2 << " are closest, " << l1 << "," << r1 << " are most distant." << '\n';
}
}
return 0;
}