AcWing196——质数距离

题目描述:
给定两个整数L和U,你需要在闭区间[L,U]内找到距离最接近的两个相邻质数C1和C2(即C2-C1是最小的),如果存在相同距离的其他相邻质数对,则输出第一对。
同时,你还需要找到距离最远的两个相邻质数D1和D2(即D1-D2是最大的),如果存在相同距离的其他相邻质数对,则输出第一对。其中L和U的差值不会超过1000000。
1≤L
题解:
这个题目很容易可以想到需要质数筛子,但是可以看到,我们的L,R的值都已经达到了1e10的级别,而我们在判断质数的时候需要用数组对每一个数进行标记,显然这个大小不允许我们这样做,所以我们需要用到离散化:把1 ~ R的数据范围缩小到L ~ R - L这样就最多需要标记1e6的数据。然后我们已知对一个整数n,它的一个质因子x一定满足x <= sqrt(n)所以我们可以先处理2~sqrt(R)范围内的质数,然后在L ~ R上剔除所有他们的倍数。这样剩下的数就一定是L ~ R范围内的质数了。
AC代码:

#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int maxn = 1e6 + 13;
const ll INF = 2147483647;
int p[maxn],prime[maxn],a[maxn],cnt1 = 0,cnt2 = 0;
void get_prime(int n)
{
    memset(prime,0,sizeof(prime));
    memset(p,0,sizeof(p));
    memset(a,0,sizeof(a));
    cnt1 = 0;
    for(int i = 2;i <= n;i++){
        if(p[i]) continue;
        prime[++cnt1] = i;
        for(int j = i;j <= n/i;j++) p[i * j] = 1;
    }
    return;
}
int main()
{
    // for(int i = 1;i <= cnt1;i++){
    //     cout << prime[i] << endl;
    // }
    ll l,r;
    while(cin >> l >> r){
        get_prime(sqrt(r));
        //筛出所有[l,r]的合数
        if(l == 1) a[0] = 1; //注意1不是质数,所以这里需要特判一下
        for(int i = 1;i <= cnt1;i++){
            int P = prime[i];
            // cout << P << endl;
            for(int j = ceil(l / P);j <= floor(r / P);j++) {
                if(j != 1) a[j * P - l] = 1;
            }
        }
        // for(int i = l;i <= r;i++){
        //     cout << i << ' ' << p[i - l] << endl;
        // }
        cnt2 = 0;
        memset(prime,0,sizeof(prime));
        for(ll i = l;i <= r;i++){
            if(a[i - l] == 0) {
                prime[++cnt2] = i;
                // cout << i << endl;
            }
            else continue;
        }
        if(cnt2 < 2) printf("There are no adjacent primes.\n");
        else{
            int maxp = 1,minp = 1;
            for(int i = 1;i < cnt2;i++){
                int d = prime[i + 1] - prime[i];
                if(d > prime[maxp + 1] - prime[maxp]) maxp = i;
                if(d < prime[minp + 1] - prime[minp]) minp = i;
            }
            printf("%d,%d are closest, %d,%d are most distant.\n",prime[minp],prime[minp + 1],prime[maxp],prime[maxp + 1]);
        }
    }
    return 0;
}

你可能感兴趣的:(算法竞赛进阶指南题解)