Loading... 题目链接:[UVA10140]([https://www.luogu.org/problemnew/show/UVA10140](https://www.luogu.org/problemnew/show/UVA10140)) ## Description 给定两个整数 $L,R$,求闭区间 $[L,R]$ 中相邻两个质数差值最小的数对与差值最大的数对。当存在多个时,输出靠前的素数对。 输入多组数据。每行两个数 $L,R$。对于全部数据,$1≤L<R<2^31,R−L≤10^6$。 (Luogu默认的翻译有点小问题,这个是kuǎi的Luogu讨论区的) ## Sol 暴力做法显然易见,直接把 $[1, R]$ 区间里面所有质数筛出来,两两比较,肯定会T掉,时间复杂度如下(线性筛) $O(\sum_{p ≤ \sqrt{R}} \frac{R-L}{p} + n) = O(\sqrt{R}\ log^2\ \sqrt{R}+(R-L)\ log^2\ R+n)$ 但是参考一下 $L,R$ 的范围光筛一遍就T掉了 同时你发现,$R-L$ 范围很小,都帮我们写好了,这肯定是提示我们快速求出 $[L,R]$ 之间的素数。 然后根据算数基本定理,知道一个合数 $n$ 必定包括一个不超过 $\sqrt{n}$ 的质因子。 所以最后我们就只要筛出 $[1,\sqrt{R}]$ 中的质数,对于每一个质数 $p$ ,在 $[L,R]$ 中标记它的倍数,这个数就一定是一个合数(见上),剩下的就是素数 所以时间复杂度为 $O(\sqrt{R}\ log^2\ \sqrt{R}+(R-L)\ log^2\ R)$ ## Code 不知道为什么UVA上会RE,算了算了,反正是对的 ```c++ #include <bits/stdc++.h> using namespace std; typedef long long LL; const int SIZE = 1000000 + 5; const int inf = 0x7f7f7f7f; int l, r; LL prime[SIZE]; int tot, vis_p[SIZE], vis[SIZE]; inline int read() { char ch = getchar(); int f = 1, x = 0; while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + ch - '0'; ch = getchar(); } return x * f; } inline void Eratosthenes() { for (int i = 2; i * i <= r; i++) { if (vis_p[i]) continue; prime[++tot] = i; for (int j = i; j <= r / i; j++) vis_p[i * j] = 1; } } inline void Flag() { memset(vis, 1, sizeof(vis)); if (l == 1) vis[0] = 0; for (int i = 1; i <= tot; i++) { for (int j = l / prime[i]; j * prime[i] <= r; j++) { LL temp = prime[i] * j; if (j > 1 && temp >= l) vis[temp - l] = 0; } } } inline void Calc() { int Max = 0, Min = inf, last = 0; int p1, p2, p3, p4; for (int i = l; i <= r; i++) { if (!vis[i - l]) continue; if (last) { int dis = abs(i - last); if (dis < Min) Min = dis, p1 = last, p2 = i; if (dis > Max) Max = dis, p3 = last, p4 = i; } last = i; } if (!Max) printf("There are no adjacent primes.\n"); else printf("%d,%d are closest, %d,%d are most distant.\n", p1, p2, p3, p4); } int main() { while (~scanf("%d %d", &l, &r)) { Eratosthenes(); Flag(); Calc(); memset(vis_p, 0, sizeof(vis_p)); memset(prime, 0, sizeof(prime)); tot = 0; } return 0; } ``` 最后修改:2021 年 09 月 07 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏