基础算法合集-埃氏筛/欧拉筛

c++算法——欧拉筛 文章目录引入模板比对 引入 大家都知道埃氏筛吧? #include <iostream> #define maxn 1005 #define endl '\n' #define LL long long #define L unsigned long long #define I unsigned int using namespace std; int visit[maxn]; void work() { ios_base::sync_with_stdio(false); 阅读详情

给定一个范围n,有q个询问,每次输出第k小的素数

输入格式

第一行包含两个正整数n, q, 分别表示查询的范围和查询的个数

接下来q行每行一个正整数k, 表示查询第k小的素数

输出格式

输出q行, 每行一个正整数表示答案

输入样例

100 3

1 

2

3

输出样例

2

3

5

数据范围

对于100%的数据,n=10^8, 1<=q<=10^6, 保证查询的素数不大于n

讲解: 从小到大枚举每个数, 如果当前数没划掉, 必定是质数, 记录该质数;枚举当前质数的倍数, 必定是合数, 划掉合数

using ll=long long;
const int N=100000010
int vis[N];
int prim[N];
int cnt;
void Eratosthenes(int n){
    for(LL i=2;i<=n;i++){
        if(!vis[i]){
            prim[++cnt]=i;
            for(LL j=i*i;j<=n;j+=i){
                vis[j]=1;
            }
        }
    }
}

补充:n=20

i=2: p{2}; v{4,6,8,10,12,14,16,18,20};

i=3: p{3}; v{9,12,15,18}

i=4:

i=5: p{5}

i=6:

i=7: p{7}

i=8,9,10'

i=11: p{11}

i=12:

i=13: p{13}

i=14,15,16:

i=17: p{17}

i=18:

i=19: p{19}

时间复杂度:O(nloglogn)

为了进一步优化会重复划掉合数的情况, 我们引入欧拉筛

欧拉筛

从小到大枚举枚举每个数

1. 如果当前数没划掉, 必定是质数, 记录该质数

2. 枚举已记录的质数(如果合数已越界则中断)

(1)  合数未越界,则划掉合数

(2) 条件 i%p==0, 保证合数只被最小质因数划掉

      若i是质数, 则最多枚举到自身中断

      若i是合数, 则最多枚举到自身的最小质数中断

const int N=100000010;
using ll=long long;
int vis[N];
int prim[N]
int cnt;
void get_prim(int n){
   for(int i=2;i<=n;i++){
        if(!vis[i]) prim[cnt++]=i;
        for(int j=1;1ll*i*prim[j]<=n;j++){
            vis[i*prim[j]]=1;
            if(i%prim[j]==0) break;
        }
    }
}

补充:

n=30

i=2: p{2}; v{4}; (2%2) break

i=3: p{3}; v{6,9}; (3%3) break;

i=4: p{5}; v{10,15,25}; (5%5) break;

i=7: p{7}; v{14,21}; (35,30)

i=8:          v{16}; (8%2) break;

i=9:          v{18,27}; (9%3) break;

i=10:        v{20}; (10%2) break;

i=11: p{11};v{22}; (33>30)

i=12:         v{24};  (12%2) break;

.......

i=16:          (32>30)

时间复杂度:O(n)

每个质数只被记录一次, 每个合数只被划掉一次

所以执行次数为O(n)

旧题新发:

An表示1,2...n的最小公倍数, 求L...R的中不同数的个数 

1=<L<=R<=10^14

R-L<=10^7 

区间筛素数 -> 求[L,R]之间所有的素数

第一步: 利用欧拉筛或者埃氏筛求2-sqrt(R) 之间的素数

第二步: 利用求的素数, 划掉L,R之间所有的非素数

素数的倍数自然就是非素数

根据上一篇文章, 我们可以得出结论

统计区间(L,R]内的素数数量cnt1。
统计区间(L,R]内的质数高次幂数量 cnt2。
最终答案=1 + cnt1 + cnt2。

统计cnt1使用区间筛法, 代码中先使用埃氏筛统计2-sqrt(R)中的所有素数

先从最小素数2开始, 2的倍数都是非素数, vis[i]=1

接着从3开始, 3^2=9, 后面顺次+3, 从平方开始是一个小优化, 因为6之前已经被2划过了

然后是5...

int n=sqrt(r);

int prim[N]; int cnt=0;

int vis[N]

for(int i=2;i<=n;i++){

        if(!vis[i]){

                prim[cnt++]=i;

                 for(ll j=i*i; i<=n;j+=i){

                        vis[j]=1;

                }        

        }

} 

接着进行对比, prim数组是从1开始进行存储素数的, is_prime[i]=true表示没有被划掉, 说明还是素数, 数组大小为区间大小 r-l+1;

for(int i=1;i<=cnt;i++){

        int x=prim[i];

        求x在[L,R]中的最小倍数

        int st=max(x*x,(l+x-1)/x*x);

        if(st<=r){

              for(ll y=st; y<=r; y+=x){

                        is_prim[y-l]=false;

               }          

        }

}

然后统计is_prim数组中素数的个数

cout(is_prim.begin(),is_prim_end(),true);

接着统计区间(L,R]内的质数高次幂数量 cnt2

ll tot_cnt=0;

统计prim数组中质数的高次方

for(int i=1; i<=cnt;i++){                遍历前cnt个质数

        int pr=prim[i];                       获取第i个质数

        ll x=(ll)pr*pr;                         从该质数的平方开始检查(因为要找的是至少是平方的幂次)

        while(x<=r){                        只要当前值不超过右边界就继续

                if(x>=l) tot_cnt++;        如果当前值大于左边界,就计数

                if(x>r/pr) break;           检查下一次乘法是否会超过r,如果是就跳出循环

                x*=pr;                          计算下一个幂次

        }

}

最后输出1 + prime_cnt + tot_cnt

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 100000010;

int vis[N];
int prim[N];
int cnt;

void Eratosthenes(int n) {
    for (ll i = 2; i <= n; i++) {
        if (!vis[i]) {
            prim[++cnt] = i;
            for (ll j = i * i; j <= n; j += i) {
                vis[j] = 1;
            }
        }
    }
}

ll count_primes(ll l, ll r) {
    ll a = sqrt(r);
    Eratosthenes(a);
    
    ll s = r - l + 1;
    vector<int> is_prime(s, true);
    if (l == 1) is_prime[0] = false;
    
    for (int i = 1; i <= cnt; i++) {
        ll x = prim[i];
        ll st = max(x * x, ((l + x - 1) / x) * x);
        for (ll y = st; y <= r; y += x) {
            is_prime[y - l] = false;
        }
    }
    
    return count(is_prime.begin(), is_prime.end(), true);
}

void solve() {
    ll l, r;
    cin >> l >> r;
    ll prime_cnt = count_primes(l + 1, r);
    
    cnt = 0;
    ll a = sqrt(r);
    Eratosthenes(a);
    
    ll tot_cnt = 0;
    for (int i = 1; i <= cnt; i++) {
        int pr = prim[i];
        ll x = (ll)pr * pr;
        while (x <= r) {
            if (x > l) ++tot_cnt;
            if (x > r / pr) break;
            x *= pr;
        }
    }
    
    cout << (1 + prime_cnt + tot_cnt) << endl;
}

int main() {
    solve();
    return 0;
}

 感谢大家的点赞和关注,你们的支持是我创作的动力!

C++三大质数筛法 阅读详情

相关推荐

解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

解题报告(十八)Codeforces - 数学题目泛做(难度:2000 ~ 3000 + )

繁凡さん的博客 5205

C++欧拉筛

然后,通过循环从2开始遍历每个数,如果该数是素数,则将其加入素数列表,并更新数组,将所有该数的倍数标记为非素数。最后,打印出所有的素数。与传统的埃拉托斯特尼筛法(Eratosthenes Sieve)相比,欧拉筛能更快地筛选出一定范围内的素数,因为它避免了不必要的筛选操作,提高了效率。欧拉筛的核心思想是保证在2到n范围内,每个合数都能被唯一地分解为其最小质因数与除自己外最大的因数相乘的形式。在使用欧拉筛时,需要注意避免对素数列表进行不必要的操作,如重复添加相同的素数,或者在不需要的地方修改数组。

JackyQWJ的博客 1525

C++欧拉筛深度解析:线性时间素数筛法的精妙实现

欧拉筛是一种高效的线性素数筛选算法,通过确保每个合数仅被其最小质因数标记一次,将时间复杂度优化至O(n)。相比传统埃氏筛法(O(n log log n)),欧拉筛避免了重复标记,核心在于if(i%x==0) break的关键终止条件。C++实现简洁,可同时计算欧拉函数等积性函数,并支持内存优化(位压缩)和分块处理超大范围。实际应用中,欧拉筛在算法竞赛和数论计算中表现优异,尤其适合需要快速素数查询或同时计算其他数论函数的场景。尽管常数因子略高,但其理论最优性使其成为大规模素数筛选的首选方案。

eniver的博客 968

欧拉筛-质数筛的神c++

欧拉筛(Euler's Sieve),又称线性筛法或欧拉线性筛,是一种高效筛选素数的方法。其核心思想是从小到大遍历每个数,同时标记其倍数为合数,但每个合数只被其最小的质因数标记一次,从而避免了重复标记,实现了线性时间复杂度的素数筛选。

szm111213的博客 2439

C++竞赛算法模板合集:从快速幂到凸包的核心模块整理

在算法竞赛中,高效且可靠的代码模板是解题速度的基石。从最基础的快速幂与素数筛,到图论中的最短路与最大流,再到动态规划的经典变体和计算几何的精度处理,每一个模块都需经过反复验证才能成为赛场上值得信赖的工具。本文从通用技术原理出发,梳理了快速幂取模、埃氏筛与欧拉筛、Dijkstra堆优化、并查集按秩合并、01背包与区间DP、凸包与旋转卡壳等核心模板的设计思路与常见陷阱,探讨如何构建一套可复现、可调试、可应对数据退化的个人模板库。无论是入门选手还是经验丰富的参赛者,都能从中找到优化自身代码组织方式与避免边界错误的

weixin_32822843的博客 158

室内无人机自主定位:融合Mid360激光雷达与光流传感器的无GPS导航实践

本文详细介绍了室内无人机自主定位技术,通过融合Mid360激光雷达与光流传感器实现无GPS导航。文章分析了技术挑战、硬件配置、算法优化及实战调试,展示了在复杂室内环境中如何实现厘米级定位精度,为仓库巡检、隧道勘测等场景提供可靠解决方案。

weixin_30500105的博客 532

素数筛法详解:埃氏筛和欧拉筛

文章目录摘要欧拉筛 摘要 本文主要介绍欧拉筛和欧拉函数。 欧拉筛 上一篇博客讲过了如何判断一个数是否是质数,那么现在要在1s内求出区间[1,1e7][1,1e7][1,1e7]内的所有质数,你会怎么做,如果对每个数都判断其是不是质数,时间复杂度是O(n∗n)O(n*\sqrt{n})O(n∗n​),数据量是1e71e71e7,这样做肯定会超时的。这就需要用到下面讲的欧拉筛法了, 欧拉筛法的时间复杂...

GD_ONE的博客 2万+

U-Net图像分割实战:从论文解析到PyTorch代码实现

本文深入解析了U-Net图像分割模型的经典架构与核心思想,并提供了从零开始的PyTorch代码实现教程。通过详细拆解编码器-解码器结构、跳跃连接等关键组件,手把手指导读者构建完整的U-Net网络,涵盖数据准备、模型训练、推理部署全流程,是掌握图像分割实战技能的实用指南。

fire9的博客 341

【算法合集】关于数论

裴蜀定理:若 a, b是整数,且 (a, b) = d,那么对于任意的整数 x, y, ax + by 都一定是 d的倍数,特别地,一定存在整数 x, y使 ax + by = d成立。

程序猿追的博客 6543

CAN总线开发必看:报文发送类型全解析(含Cycle/Event/CE/IfActive对比)

本文深入解析CAN总线开发中的四种报文发送类型(Cycle/Event/CE/IfActive),对比其核心特征与工程应用场景。通过典型ECU交互案例和决策矩阵,帮助开发者根据实时性、总线效率等需求选择最优方案,并详解信号发送模式与恢复机制,提升车载网络通信可靠性。

weixin_30632089的博客 310

RH850从0搭建Autosar开发环境【7】- Davinci Configurator之CanTp模块配置详解(上)

RH850从0搭建Autosar开发环境【7】- Davinci Configurator之CanTp模块配置详解(上)

weixin_42412049的博客 2296

数学--数论---欧拉筛 模板

typedef long long ll; bool ok[maxn]; int prime[maxn],phi[maxn],cnt; void sieve() { phi[1]=1; for(ll i=2;i<maxn;++i) { if(!ok[i]) { prime[cnt++]=i; phi[i]=i-1; } for(int j=0...

日拱一卒,功不唐捐 2868

13. MIC配置

恒玄BES2700,支持3个MIC。

雪飞_海 924

【欧拉筛求素数】

​ 普通求素数是对每一个数的因子进行枚举,进而判断它是否是素数,但会很慢。 进阶一点的是埃式筛法,埃式筛法的基本思想就是,当我们遍历到一个素数时,把所有该素数的倍数(自然是合数)都筛选出来。但是这样同样会有重复筛选的情况而浪费时间,比如2的倍数有6,而3的倍数同样会把6,再次筛选一遍。 于是便有了欧拉筛来求素数的方法。 int prime[MAXN]; bool vis[MAXN]; int cnt=0; void Euler_prime(int n) { for(int i=2; i<=n; ++

Kokli的博客 650

CKS-CN考试之路----04

根据上面信息我们知道,这个pod运行在default命名空间下,pod名字为cpu-77cd5ddcbf-bvb8w。可以从/etc/falco/falco_rules.yaml中获得相关内容,大概在文件的460行左右.编辑/etc/falco/falco_rules.local.yaml。7c688a8bfd69即是我们想要获得的docker id。将行为不当 Pod 的 Deployment 缩放为零副本。根据我们刚才定义的rule生成报告。访问/dev/mem 的 Pod。那么如果考试记不住怎么办?

Q先生 599

C#解析基恩士(KEYENCE)PLC数据:KV协议通信与实时监控实现

KV协议是基恩士PLC使用的一种专用通信协议,通常用于与上位机进行数据交换。KV协议通过RS-232C、RS-485、Ethernet等接口与上位机通信,支持多种数据类型的读写,包括但不限于位、字、双字、浮点数等。简洁易用:KV协议的通信格式简单,易于实现。支持多种数据类型:支持位数据、字数据、定长字符串等。高效实时性:能够提供较高的实时数据交换性能,适合实时监控应用。本文介绍了如何通过C#与基恩士KV系列PLC进行通信,实现数据的解析和实时监控功能。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1806

蓝桥杯国赛数论模板:从欧拉筛到逆元,实战代码与避坑指南

在算法竞赛和编程实践中,数论是处理整数性质与运算的核心数学分支,其基础概念如素数、同余和最大公约数是解决复杂问题的基石。从原理上讲,欧拉筛通过线性时间复杂度高效筛选素数,而模运算下的乘法逆元则借助扩展欧几里得或费马小定理实现,它们共同构成了模意义下除法的关键。这些技术的工程价值在于,将严密的数学理论转化为稳定、高效的代码模块,能极大提升算法实现的可靠性和开发效率。应用场景广泛覆盖密码学、组合数学以及算法竞赛中的高精度计算问题。本文聚焦于【欧拉筛】和【乘法逆元】这两个热点的实现细节与实战组合,为蓝桥杯等竞赛提

weixin_32181267的博客 232

【代码版本管理】SVN(Subversion)

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对SVN(Subversion)代码版本管理做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容。

qq_35635374的博客 668

模板 - 数论

一:【质数】 1.【暴力判】 【模板】素数、コンテスト、素数 [AT807] #include<cstdio> #include<cmath> int x; inline bool judge(int n){ if(n<4)return 1; if(n%2==0)return 0; int half=sqrt(n); for(int i=3;i<=half;i+=2) if(n%i==0)return 0; retu

繁凡さん的博客 693

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

蓝桥杯_算法基础【合集】

快速排序 #include <iostream> using namespace std; //#include<algorithm> sort(q,q+n); const int N = 1e6 + 10; int quick_n; int quick_q[N]; void quick_sort(int quick_q[],int l,int r) { if(l >= r) { return ; } int x = quick_q[l],i = l - 1,j

violet的博客 1186

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

因数与质数算法模板合集:从质数判定到因数枚举的实战指南

因数与质数是数论和算法中的基础概念,理解其原理是掌握更高级算法(如RSA加密)的基石。因数是能整除给定数的数,而质数是只有1和自身两个因数的数。在计算机科学中,高效处理质数和因数问题具有重要价值,广泛应用于算法竞赛、密码学、数据加密和业务逻辑优化等场景。本文聚焦于**质数判定**和**质因数分解**这两个核心操作,提供了从基础的试除法到高效的埃拉托斯特尼筛法、线性筛(欧拉筛)等一系列经过实战检验的代码模板。这些模板能帮助开发者快速解决如LeetCode“计数质数”等常见问题,并优化程序性能,避免因暴力求解导

weixin_33883104的博客 235

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

python反素数算法优化_合数

python中判断一个数是不是质数2020-12-18 16:57:27首先说明,内容结合了其他人的编程想法 和其他学习平台学习的思路,本人只是将解法记录下来方便自己之后查阅。由于本人学艺不精,如果有错误还请大家见谅并指出,谢谢。质数是除了1和它本身再无其他的因数,例如5。在数学上与质数相对的是合数。其中1既不是质数也不是合数。num = inleetcode204. 计数质数2020-12-03...

weixin_39585617的博客 979

因数与质数算法模板合集:从试除法到Miller-Rabin的实战指南

因数与质数是算法与编程的基石,理解其核心概念是解决复杂数论问题的关键。因数是能整除给定数的整数,而质数是大于1且仅能被1和自身整除的数。其原理基于数论基础,通过不同的算法实现高效计算。在技术价值上,高效的质数判断与因数分解算法能极大提升程序性能,避免性能陷阱。这些算法广泛应用于密码学(如RSA加密)、竞赛编程、科学计算及需要数学运算的各类工程场景。本文提供的**因数质数模板合集**,涵盖了从基础的试除法、高效的埃拉托斯特尼筛法与线性筛,到处理大数的**Miller-Rabin素性测试**等核心实现,并详细解

weixin_34072296的博客 257

数据结构(严蔚敏版)与算法的实现(含全部代码)_数据结构与算法严蔚敏代码csdn

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新如果你需要这些资料,可以戳这里获取C++ string的简单使用C++ 类型转换(内置类型,string、char*、const char*等)质因子分解除树和图外的数据结构可以使用STL: C++ STL的使用数据结构线性表顺序表循环左移(

2401_85015191的博客 1254

板子合集2.0

本板子是集成我的板子和OIWIKI。

JK01WYX的博客 1270

模板:数学有关

试除法 O(n)O(\sqrt{n})O(n​) bool prime(int n) { if (n < 2) return 0; for (int i = 2; i * i <= n; i++) if (n % i == 0) return 0; return 1; } Eratosthenes筛法 O(nloglogn)O(n loglogn)O(nloglogn) in...

P-O-D的博客 skr~ 338
上一篇: AtCoder Beginner Contest 412
下一篇: 基础算法合集-图论
一只鱼^_
博客等级 码龄3年 1073粉丝 92原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值