--- title: "质数距离" created: 2025-11-28 tags: - 算法 --- # 质数距离 ## 题目 [质数距离](https://www.acwing.com/problem/content/198/) ![[image-d5a1cba1.png]] ## 思路分析 找距离最近和距离最远的相邻质数对 假设所有的质数已经找出来了 那么就是做一遍双指针 用max维护prime[i+1]-prime[i]的最大值 用min维护prime[i+1]-prime[i]的最小值 记录相应最大最小的i 但问题在于 如何找到[L,U]范围内的所有质数 用筛法的话(依赖于第一个素数2 得从2开始) 得筛2~$2^{31}-1$ 这显然不现实 然后取大于L的第一个质数作为左边界 又是一个问题 换个思路 从L到U 用试除法判断素数的话 左边界的问题解决了 但是时间复杂度为$O(nlog\sqrt{m})$约等于 $10^{10}$(其中n为区间长度$10^6$,m为数字大小 $10^9$ 很可能会超时 但也不是不能做 考试的时候能分析到这里拿个70分就差不多了 ```cpp #include using namespace std; int L,U; int main() { while(cin>>L>>U){ vector legal_primes; for(int i=L;i<=U;i++){ bool is_prime=true; if(i<2) is_prime=false; for(int j=2;j<=i/j;j++){ if(i%j==0){ is_prime=false; continue; } } if(is_prime) legal_primes.push_back(i); } int cnt=legal_primes.size(); // cout<legal_primes[maxp+1]-legal_primes[maxp]) maxp=i; } cout< using namespace std; typedef long long LL; const int N = 50000; // 用于筛选 sqrt(r) 内的素数 const int M = 1000010; // 大于 r-l 的最大范围 bool st[N], isPrime[M]; // st用于筛 sqrt(r) 内的素数,isPrime用于标记区间[l, r]内的数是否为素数 int primes[N], cnt; // primes数组存放所有小于等于 sqrt(r) 的素数,cnt为计数器 // 线性筛 所有小于sqrt(r)的素数 void get_primes(int n) { memset(st, 0, sizeof st); cnt = 0; for (int i = 2; i <= n; ++i) { if (!st[i]) { primes[cnt++] = i; for(int j=i;j<=n;j+=i) primes[j]=true; } } } int main() { int l, r; while (~scanf("%d%d", &l, &r)) { get_primes((int)sqrt(r) + 1); memset(isPrime, true, sizeof isPrime); for (int i = 0; i < cnt; ++i) { LL p = primes[i]; LL start = max(p * 2, (l + p - 1) / p * p); // 计算在区间[l, r]内p的最小倍数 for (LL j = start; j <= r; j += p) isPrime[j - l] = false; // 标记合数 } // 收集区间[l, r]内的所有素数 vector segmentPrimes; for (int i = 0; i <= r - l; ++i) if (isPrime[i] && i + l > 1) // 排除1 segmentPrimes.push_back(i + l); if (segmentPrimes.size() < 2) printf("There are no adjacent primes.\n"); else { // 寻找距离最近和最远的素数对 int minp = 0, maxp = 0; for (int i = 0; i + 1 < segmentPrimes.size(); ++i) { int d = segmentPrimes[i + 1] - segmentPrimes[i]; if (d < segmentPrimes[minp + 1] - segmentPrimes[minp]) minp = i; if (d > segmentPrimes[maxp + 1] - segmentPrimes[maxp]) maxp = i; } printf("%d,%d are closest, %d,%d are most distant.\n", segmentPrimes[minp], segmentPrimes[minp + 1], segmentPrimes[maxp], segmentPrimes[maxp + 1]); } } return 0; } ``` ## 同类题型 ## 视频讲解 --- ⬅️ [[筛素数|筛素数]] 🏠 [[00-刷题理模型]] ➡️ [[阶乘分解|阶乘分解]]