质数距离《算法竞赛进阶指南》 \Huge{质数距离《算法竞赛进阶指南》} 质数距离《算法竞赛进阶指南》
题目地址:196. 质数距离 - AcWing题库
给定两个整数 L L L 和 U U U,你需要在闭区间 [ L , U ] [L,U] [L,U] 内找到距离最接近的两个相邻质数 C 1 C_1 C1? 和 C 2 C_2 C2?( C 1 < C 2 C_1 < C_2 C1?<C2?)(即 C 2 ? C 1 C_2-C_1 C2??C1? 是最小的),如果存在相同距离的其他相邻质数对,则输出第一对。
同时,你还需要找到距离最远的两个相邻质数 D 1 D_1 D1? 和 D 2 D_2 D2?( D 1 < D 2 D_1 < D_2 D1?<D2?)(即 D 2 ? D 1 D_2-D_1 D2??D1? 是最大的),如果存在相同距离的其他相邻质数对,则输出第一对。
每行输入两个整数 L L L 和 U U U,其中 L L L 和 U U U 的差值不会超过 1 0 6 10^6 106。
对于每个 L L L 和 U U U,输出一个结果,结果占一行。
结果包括距离最近的相邻质数对和距离最远的相邻质数对。(具体格式参照样例)
如果
L
L
L 和
U
U
U 之间不存在质数对,则输出 There are no adjacent primes.
。
1 ≤ L < U ≤ 2 31 ? 1 1 \le L < U \le 2^{31}-1 1≤L<U≤231?1
2 17
14 17
2,3 are closest, 7,11 are most distant.
There are no adjacent primes.
本题为多实例。
每次给出一个区间 [ l , r ] [l,r] [l,r],然后求区间内的质数中,相邻且差值最大和差值最小的两组质数。
具体做法如下,但需要注意几个问题:
vector<int> p(N);
bool q[N];
int tot;
void primes(int n) {
for(int i = 2; i <= n; i ++ ) {
if(!q[i]) p[tot++] = i;
for(int j = 0; p[j] <= n / i; j ++ ) {
q[p[j] * i] = 1;
if(i % p[j] == 0) break;
}
}
}
void Solved() {
LL l, r;
primes(50000); //预处理出50000以内的质数
while(cin >> l >> r) {
int mi = INF, mx = -1;
vector<int> a;
memset(q, false, sizeof q); //重复利用,更加环保
for(int i = 0; i < tot; i ++ ) {
//从大于l的最小的p[i]的倍数开始枚举
for(LL j = max(2ll * p[i], (l + p[i] - 1) / p[i] * p[i]); j <= r; j += p[i] ) {
q[j - l] = true; //数太大了,需要减去l这个偏移量
}
}
for(int i = 0; i <= r - l; i ++ ) //统计区间的质数
if(!q[i] && i + l > 1) a.push_back(i + l); //记得把偏移量l加回来
if(a.size() < 2) {
cout << "There are no adjacent primes.\n"; continue;
}
for(int i = 0; i < a.size() - 1; i ++ ) {
int x = a[i + 1] - a[i];
if(x < a[mi] - a[mi - 1]) mi = i;
if(x > a[mx] - a[mx - 1]) mx = i;
}
cout << a[mi] << "," << a[mi + 1] << " are closest, ";
cout << a[mx] << "," << a[mx + 1] << " are most distant.\n";
}
}