Prime Distance

题目

image

题目大意

给定两个整数\(L\)\(U\),你需要在闭区间\([L,U]\)内找到距离最接近的两个相邻质数\(C_1\)\(C_2\)(即\(C_2−C_1\)是最小的),如果存在相同距离的其他相邻质数对,则输出第一对。
同时,你还需要找到距离最远的两个相邻质数\(D_1\)\(D_2\)(即\(D_1−D_2\)是最大的),如果存在相同距离的其他相邻质数对,则输出第一对。


思路

性质

  • 性质1:若一个数是合数那必然存在两个因子\(d\)\(\frac{n}{d}\),假设\(d\leq \frac{n}{d}\),则\(d\leq \sqrt{n}\),即\(n\)必然存在一个小于\(\sqrt{n}\)的因子。

分析

对于朴素的做法我们不难想出,打表筛除\(1\)\(2^{31}-1\)之间的所有质数,然后对于每一个区间\([L,U]\)只需从头到尾遍历一遍即可。
但是这样必定会\(TLE\),所以我们需要挖掘出某些性质对其进行优化。而借助线性筛的原理,我们可以知道每一个合数都可以被其最小的质因子筛除。再根据上面的性质我们可知对于小于\(2^{31}-1\)的最大合数也必然存在一个小于\(\sqrt{2^{31}-1}\)的质因子。

步骤

  1. 筛出\(1\)\(2^{31}-1\)的所有质数。
  2. 对于每一个区间\([L,U]\)使用筛出的\(1\)\(2^{31}-1\)的所有质数进行二次筛除。
  3. 遍历区间\([L,U]\)找出答案。

注意事项

题目范围较大,会爆\(int\),我们需要开\(long long\)来存储。


代码

typedef long long LL;

const int N = 1000010;

int primes[N], cnt;
LL l, r;
bool st[N];

void init(int n) // 线性筛
{
    for (int i = 2; i <= n; i ++ ) 
    {
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] * i <= n; i ++ ) 
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

int main() 
{
    init(N - 1);
    
    while (cin >> l >> r) 
    {
        memset(st, 0, sizeof st); // 重复使用st数组
        for (int i = 0; i < cnt; i ++ ) 
        {
            LL t = (l + primes[i] - 1) / primes[i];
            for (LL j = max(t, (LL)2); (LL)primes[i] * j <= r; j ++ ) 
                st[(LL)primes[i] * j - l] = true; // 将l~r的下标映射到0~r-l
        }
        
        vector<int> q;
        for (LL i = l; i <= r; i ++ ) 
            if (!st[i - l] && i != 1) // 1既不是质数也不是合数
                q.push_back(i);
                
        if (q.size() <= 1) 
        {
            puts("There are no adjacent primes.");
            continue;
        }
                
        int maxl, maxr, maxres = -1;
        int minl, minr, minres = 0x3f3f3f3f;
        for (int i = 0; i < q.size() - 1; i ++ ) 
        {
            if (q[i + 1] - q[i] < minres)
            {
                minres = q[i + 1] - q[i];
                minl = q[i], minr = q[i + 1];
            }
            if (q[i + 1] - q[i] > maxres) 
            {
                maxres = q[i + 1] - q[i];
                maxl = q[i], maxr = q[i + 1];
            }
        }
        printf("%d,%d are closest, %d,%d are most distant.\n", minl, minr, maxl, maxr);
    }
    
    return 0;
}
posted @ 2021-05-05 17:59  筱翼深凉  阅读(86)  评论(0编辑  收藏  举报