Prime Distance

题面

  • 给定两个正整数 ,求 相邻 的两个差最大的质数和 相邻 的两个差最小的质数。如果区间内质数个数 ,输出 There are no adjacent primes.

样例 #1

样例输入 #1

2 17
14 17

样例输出 #1

2,3 are closest, 7,11 are most distant.
There are no adjacent primes.

思路

如果是 1e6 范围内, 直接线性筛求质数然后枚举所有相邻的质数对判断即可。

但这里是 , 为 int 类型的最大值, 显然无法直接进行从 1 筛到头。

想个法子优化优化。可以发现我们要查询的区间还是只有 1e6, 那么若能求出来里面的所有质数, 就可以直接线性查询。

思考这样一个性质: 对于一个数 , 它的质因子 一定满足不等式 , 数 只能由相对于 一大一小两个因子相乘, 或者俩 相乘得出。

那么当我们想求 的质因子时, 就可以先线性筛 的质数, 然后对于每个质数, 用欧拉筛的思路枚举该质数的倍数, 将结果筛掉即可。之后再枚举 区间内的数, 把质数都放到一个数组 中, 最后再根据该数组求解。

时间复杂度计算:

筛质数部分

得出的质数个数可以用素数定理 得出, 大约为

用质数来筛掉 区间时, 若当前质因子为 , 可以直接从区间内最小的质因子倍数开始筛, 即 (此时的除法是下取整), 注意该起点也必须至少大于

而质因子 区间内的枚举其倍数的次数为 (设区间长度为n) , 分数和部分其级别是跟 同一级, 故这一步的时间复杂度大概是 , 可以认为是

最后同样也是 扫描一遍, 故整体时间复杂度也是

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
// #define debug
const int N = 1e6 + 10, M = 5e4 + 10;
LL primes[N], cnt;
bool st[N];
LL l, r;
 
void init()
{
    memset(primes, 0, sizeof primes);
    memset(st, 0, sizeof st);
    cnt = 0;
    for (int i = 2; i <= M; i++)
    {
        if (!st[i])
            primes[cnt++] = i;
        for (int j = 0; primes[j] * i <= M; j++)
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0)
                break;
        }
    }
}
 
void solve()
{
    init();
    memset(st, 0, sizeof st);
    for (int i = 0; i < cnt; i++)
    {
        LL p = primes[i];
        for (LL j = max((l + p - 1) / p * p, p * 2); j <= r; j += p)
            st[j - l] = true;
    }
 
    cnt = 0;
    for (int i = 0; i <= r - l; i++)
        if (!st[i] && i + l >= 2)
            primes[cnt++] = i + l;
 
    if (cnt <= 1)
    {
        cout << "There are no adjacent primes." << endl;
        return;
    }
 
    int maxp = 0, minp = 0;
    for (int i = 0; i + 1 < cnt; i++)
    {
        int sub = primes[i + 1] - primes[i];
        if (sub > primes[maxp + 1] - primes[maxp])
            maxp = i;
        if (sub < primes[minp + 1] - primes[minp])
            minp = i;
    }
    printf("%d,%d are closest, %d,%d are most distant.\n",
           primes[minp], primes[minp + 1],
           primes[maxp], primes[maxp + 1]);
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while (cin >> l >> r)
    {
        solve();
    }
    return 0;
}