筛指定区间的素数[区间偏移二次筛法]

引入问题:


给定两个整数L和U,你需要在闭区间[L,U]内找到距离最接近的两个相邻质数C1和C2(即C2-C1是最小的),如果存在相同距离的其他相邻质数对,则输出第一对。
同时,你还需要找到距离最远的两个相邻质数D1和D2(即D1-D2是最大的),如果存在相同距离的其他相邻质数对,则输出第一对。
1 ≤ L < U ≤ 2 31 − 1 , U − L ∈ [ 0 , 1 e 6 ] 1≤L<U≤2^{31}−1,U-L\in[0,1e6] 1L<U2311,UL[0,1e6]


解题思路:


(1) 2 31 − 1 ≈ 1 e 9 2^{31}-1\approx1e9 23111e9无论是欧拉筛还是埃氏筛法都是从 [ 1 , n ] [1,n] [1,n]开始筛的,这个数据范围都是无法接受的
(2)很明显如果这个一个数的是合数:那么这个数一定有一个质因子 d < = n d<=\sqrt n d<=n
(3)那么我们就先把 [ 1 , n ] [1,\sqrt n] [1,n ]内的素数筛出来 1 e 9 ≈ 5 e 4 \sqrt {1e9}\approx5e4 1e9 5e4可以接受
(4)那么我们就把这些素数去筛 [ L , U ] [L,U] [L,U]的素数
(5)根据埃氏筛法我们要找到 [ L , U ] [L,U] [L,U]这个区间内第一个大于质数 p p p,并且是 p p p的倍数之后就每次 + p +p +p一次筛下去;
(6)第一个大于 p p p并且是 p p p的倍数 ⌈ L p ⌉ ∗ p ≈ ⌊ L + p − 1 p ⌋ ∗ p \lceil {L\over p} \rceil*p\approx\lfloor {L+p-1\over p} \rfloor*p pLppL+p1p
(7)因为数很大我们可以让 [ [ [区间整体 − L ] ∈ [ 0 , 1 e 6 ] -L]\in[0,1e6] L][0,1e6]


代码


题目链接(qwq)戳我

#include <bits/stdc++.h>

using namespace std;
const int N = 6e6 + 10;
long long prime[N], cnt;
bool vis[N];

 void init(int n)
 {
     cnt = 0;
     memset(vis,0,sizeof (vis));
     for(int i = 2; i <= n; ++ i)
     {
         if(!vis[i]) prime[cnt ++] = i;
         for(int j = 0; j < cnt && i * prime[j] <= n; ++ j)
         {
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) break;
         }
     }
 }

int main()
{
    long long l, r;
    while(cin >> l >> r)
    {
        init(50000);//Eula筛
        memset(vis,0,sizeof (vis));
        for(int i = 0; i < cnt; ++ i)
        {
            long long p = prime[i];
            for(long long j = max(2 * p, (l + p - 1) / p * p); j <= r; j += p)
              vis[j - l] = true;//减去偏移量
        }
        cnt = 0;
        for(long long i = 0; i <= r - l; ++ i)
          if(!vis[i] && i + l >= 2)
            prime[cnt ++] = i + l;
        int maxp = 0, minp = 0;
        for(int i = 0; i < cnt - 1; ++ 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;
        }
        if(cnt < 2) puts("There are no adjacent primes.");
        else 
        {
             cout << prime[minp] << "," << prime[minp + 1] << " are closest, ",
             cout << prime[maxp] << "," << prime[maxp + 1] << " are most distant.\n";
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值