题意
给出 l l 和,求出在 l∼r l ∼ r 中的相邻的质数之间最远的和最近的。
思路
因为数据范围很大,我们不能直接把质数筛到
r
r
,但我们可以筛到,然后再利用这些质数标记出
l∼r
l
∼
r
中的合数,剩下的就是
l∼r
l
∼
r
的质数了,然后我们两两判断就行了。
还有标记合数时下标-l+1,可以省去很多空间,不然过不了。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
int l, r, m, t, prime[46341], v[46341], ans[1000001], noans;
void init() {//预处理1~sqrt(数据范围)的质数
for (int i = 2; i <= 46340; i++) {
if (v[i]) continue;
prime[++m] = i;
for (int j = i; j <= 46340 / i ; j++) v[i * j] = 1;
}
}
void work() {
memset(ans, 0, sizeof(ans));
if (l == 1) ans[1] = 1;
for (int i = 1; i <= m; i++)//标记l~r的合数
{
int j = ceil((double)l / prime[i]);
if (j == 1) j++;
for (; j <= floor((double) r / prime[i]); j++) ans[prime[i] * j - l + 1] = 1;
}
int ans1, ans2 = 2147483647, ans3 = 2147483647, ans4, last = 0;
for (int i = 1; i <= r - l + 1; i++) {
if (ans[i]) continue;
if (!last) {
last = i;
continue;
}
if (i - last < ans2 - ans1) {
ans1 = last;
ans2 = i;
}
if (i - last > ans4 - ans3) {
ans3 = last;
ans4 = i;
}
last = i;
}
if (ans2 == 2147483647) printf("There are no adjacent primes.\n");
else printf("%d,%d are closest, %d,%d are most distant.\n", ans1 + l - 1, ans2 + l - 1, ans3 + l - 1, ans4 + l - 1);
}
int main() {
init();
while (scanf("%d %d", &l, &r) != EOF) work();
}