欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > 洛谷P1835 素数密度(分段筛的思想)

洛谷P1835 素数密度(分段筛的思想)

2025/6/24 4:53:51 来源:https://blog.csdn.net/lylzsx20172018/article/details/148759689  浏览:    关键词:洛谷P1835 素数密度(分段筛的思想)

题目描述

给定 L , R L,R L,R,请计算区间 [ L , R ] [L,R] [L,R] 中素数的个数。

1 ≤ L ≤ R < 2 31 1\leq L\leq R < 2^{31} 1LR<231 R − L ≤ 10 6 R-L\leq 10^6 RL106

输入格式

第一行,两个正整数 L L L R R R

输出格式

一行,一个整数,表示区间中素数的个数。

输入输出样例 #1

输入 #1

2 11

输出 #1

5

提交链接

素数密度

思路分析

R 的上限接近 2 31 2^{31} 231,数量级为 10 9 10^9 109 ,因此不能对整个区间直接进行素数筛。

引入:

合数:是指大于 1 1 1 且不是素数的数,也就是说它可以表示成两个大于 1 1 1 的整数的乘积。

<=> x = a × b x = a × b x=a×b,其中 1 < a ≤ b < x 1 < a ≤ b < x 1<ab<x ----> a ≤ x a ≤ \sqrt{x} ax b ≤ x b ≤ \sqrt{x} bx

考虑最大范围,每个合数 x x x 至少有一个因数 ≤ R ≤ \sqrt{R} R 。并且这个因子一定为素数(要么是素数,要么能进一步分解成素数(唯一分解定理))

得到:

在这里插入图片描述

  1. 埃氏筛预处理 [ 1 , 1 e 5 ] [1 , 1e5] [1,1e5] 范围内的素数。

    const int maxn = 1e5;
    typedef long long LL;
    bool is_prime[maxn + 9];
    vector<long long> p;is_prime[0] = is_prime[1] = true;for (LL i = 2; i <= maxn; i++)
    {if (!is_prime[i]){p.push_back(i);for (LL j = i * i; j <= maxn; j += i)is_prime[j] = true;}
    }
    
  2. 每一个素数 p p p ,标记处于 [ L , R ] [L , R] [L,R] 范围内的倍数。(埃氏筛思想

    找到素数 p p p [ L , R ] [L , R] [L,R] 中的第一个倍数,然后从那开始每隔 p p p 个数筛掉一次。

    起始位置: strat = strat = max(p * p, (L + p - 1) / p * p);

  3. 利用 R − L ≤ 10 6 R - L ≤ 10^6 RL106 的关系,引入小范围的标记数组。

    R R R 可能高达 2 31 2^{31} 231,我们不能直接开一个大小为 R + 1 R + 1 R+1 的数组,内存根本放不下。

    引入:bool check[1000009];

    c h e c k [ i ] check[i] check[i] 表示 L + i L + i L+i 是否为素数((对原始区间 [ L , R ] [L,R] [L,R]的“映射”)

  4. 特殊情况处理。

    L = 1 L = 1 L=1 时,数值 1 1 1 本身不会被任何素数筛掉,必须手动将其标记为非素数。

参考代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
typedef long long LL;
bool is_prime[maxn + 9], check[1000009];
vector<long long> p;void init() // 埃氏筛  预处理1e5范围内的素数
{is_prime[0] = is_prime[1] = true;for (LL i = 2; i <= maxn; i++){if (!is_prime[i]){p.push_back(i);for (LL j = i * i; j <= maxn; j += i)is_prime[j] = true;}}
}int main()
{init();LL l, r;cin >> l >> r;for (int i = 0; i < p.size(); i++) // 每一个素数去筛[l,r]范围内的非素数{LL x = max(p[i] * p[i], (l + p[i] - 1) / p[i] * p[i]); // 起始位置for (LL j = x; j <= r; j += p[i])check[j - l] = true; // 映射}if (l == 1)check[0] = true;   //特殊情况处理int cnt = 0;for (int i = l; i <= r; i++){if (!check[i - l])cnt++;}cout << cnt;return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词