ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

196. 质数距离 (筛素数,离散化)

2022-02-09 16:34:09  阅读:194  来源: 互联网

标签:50000 P0 int 质数 196 cnt 素数 ll


196. 质数距离 - AcWing题库 

这里参考于大佬的题解:AcWing 196. 质数距离 - AcWing

前言:由于L,U最大可以取到2^32-1,2^31-1是约等于2e9,如果采用普通的线性筛法的话,无论是时间复杂度还是空间复杂度都是O(n)==O(2e9),那必然是会超时的,那么我们就思考一下怎么做出优化。

分析:由于注意到 L,U 的差值只是1e6,那么采用O(n)或者O(nlogn)的做法

总结一下y总的思路,如下

  • 一个合数n的两个因子,必然有一个不会超过sqrt(n),那么sqrt(2^31)≈50000,可以在时间复杂度接受的范围之中
  • 如果n是合数,那么一定存在在(1~50000)中间有一个因子P,(1<P<n)

步骤

  • 首先筛选出1~50000内所有的质数
  • 运用埃氏筛质数法,1~50000内所有的质数P在[L,R]中的倍数都被染色成为合数,剩下没有被染色的就是质数

埃氏筛质数法:保证一个数只会被他的质因子染色,也就是说用质因子去染色在[L,R]范围内的所有倍数,首先为了避免不必要的操作,需要先计算出在(L,R)范围内,关于质因子p的最小倍数,

也就是L/p (上取整),等价于 L+p-1/p (下取整)。那么在埃氏筛法里面,模板如下

for (int i = 0;i < cnt;i++)
{
      int P0 = primes[i];//至少是2倍,不然质数本身会被染色,或者[L/p]倍,所以取最大值
      for (ll j = max(0ll + 2 * P0, (l + P0 - 1) / P0*P0);j <= u;j += P0)
      {//离散化的步骤,用j-l离散化
            st[j - l] = true;   //表示j是一个合数          
      }
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define x first
#define y second
using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
bool st[N];
int primes[N];
int cnt;
int mp[N];
ll ans[N];
void print()
{
    cout << 1 << ' ';
    exit(0);
}
void solve(int n)
{//欧拉筛法
    cnt = 0;memset(st, 0, sizeof st);
    for (int i = 2;i <= n;i++)
    {
        if (!st[i]) primes[cnt++] = i;
        for (int j = 0;primes[j] <= n / i;j++)
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
int main()
{
    ll l, u;
    while (cin >> l >> u)
    {
        memset(ans, 0, sizeof ans);
        solve(50000);
        memset(st, 0, sizeof st);
        for (int i = 0;i < cnt;i++)
        {
            int P0 = primes[i];
            for (ll j = max(0ll + 2 * P0, (l + P0 - 1) / P0*P0);j <= u;j += P0)
            {
                st[j - l] = true;   //表示j是一个合数          
            }
        }
        cnt = 0;
        for (int i = 0;i <= u - l;i++)
        {   //由于2不是一个质数,所以要特判一下
            if (!st[i]&&i+l>=2) ans[cnt++] = i + l;
        }
        int maxx = 0, minn = 0;
        for(int i=0;i+1<cnt;i++)
        {
            int d=ans[i+1]-ans[i];
            if(ans[maxx+1]-ans[maxx]<d) maxx=i;
            if(ans[minn+1]-ans[minn]>d) minn=i;
        }
        if(cnt<2) printf("There are no adjacent primes.\n");
        else
        {
            printf("%d,%d are closest, %d,%d are most distant.\n",ans[minn],ans[minn+1],ans[maxx],ans[maxx+1]);
        }
    }
    return 0;
}

标签:50000,P0,int,质数,196,cnt,素数,ll
来源: https://blog.csdn.net/qq12323qweeqwe/article/details/122841954

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有