1 条题解

  • 0
    @ 2026-10-26 13:00:02

    思路与算法

    先筛出2至46340的质数,因为R<2^31,其平方根不超过这个值。对每个[L,R]创建布尔段,依次用小质数p标记其倍数,起点为max(p²,ceil(L/p)*p)。单独排除1,再从左到右扫描剩下的质数,比较相邻差,分别维护最小和最大差对应数对;相等时不更新。

    正确性说明

    区间内任意合数都有一个不超过sqrt(R)的质因子,因而一定被某轮标记。起点不小于p²,避免把p自身误删,区间内质数均保留。递增扫描使每一对相邻质数恰好比较一次,严格更新保留最先出现的并列数对。若不足两质数,没有相邻数对,输出指定英文句子。

    复杂度

    设B=46340、W=R-L+1≤1000001。预筛初始化O(B),筛法O(B log log B),每组段初始化O(W),标记约O(W log log R+π(sqrt(R))),扫描O(W)。空间O(B+W),多组复用小质数表。起点乘法、p²与区间端点用long long,防止32位中间计算溢出。

    易错点

    1不是质数,L本身若为小质数不能删除。closest与most distant并列时取靠前数对。逗号后、句点和英文大小写按样例输出。独立答案逐整数用32位范围确定性的Miller-Rabin底数2、3、5、7、11验证,未复用分段筛标记结果。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        const int cap = 46340;
        vector<bool> isPrime(cap + 1, true);
        vector<int> primes;
        for (int i = 2; i <= cap; ++i)
            if (isPrime[i]) {
                primes.push_back(i);
                for (long long j = 1LL * i * i; j <= cap; j += i)
                    isPrime[j] = false;
            }
        long long L, R;
        while (cin >> L >> R) {
            vector<bool> ok(R - L + 1, true);
            for (long long p : primes) {
                if (p * p > R)
                    break;
                for (long long j = max(p * p, (L + p - 1) / p * p); j <= R; j += p)
                    ok[j - L] = false;
            }
            if (L == 1)
                ok[0] = false;
            long long last = -1, al = -1, ar = 0, bl = -1, br = 0;
            for (long long x = L; x <= R; ++x)
                if (ok[x - L]) {
                    if (last >= 0) {
                        if (al < 0 || x - last < ar - al) {
                            al = last;
                            ar = x;
                        }
                        if (bl < 0 || x - last > br - bl) {
                            bl = last;
                            br = x;
                        }
                    }
                    last = x;
                }
            if (al < 0)
                cout << "There are no adjacent primes.\n";
            else
                cout << al << ',' << ar << " are closest, " << bl << ',' << br
                     << " are most distant.\n";
        }
    }
    
    • 1

    信息

    ID
    1744
    时间
    1000ms
    内存
    512MiB
    难度
    普及
    标签
    递交数
    1
    已通过
    1
    上传者