c++入门必学算法 质数筛
文章目录
- 一、什么是质数筛
- 二、暴力枚举
- 1、暴力枚举基本思想:
- 2、模板代码
- 3、运行结果
- 三、埃氏筛
- 1、埃氏筛基本思想:
- 2、模板代码
- 3、运行结果
- 四、欧拉筛
- 1、对比埃氏筛
- 2、欧拉筛的基本思想
- 3、模板代码
- 3、运行结果
- 五、总结
一、什么是质数筛
质数筛也叫素数筛,是求1到n之内素数的优化算法,质数筛有两种,埃氏筛和欧拉筛。
埃氏筛的时间复杂度接近O(n*logn),而欧拉筛可以把复杂度降低到O(n),下面看两种算法的到底是如何一步步优化的吧
二、暴力枚举
暴力法求解复杂度O(n)*n\sqrt{n}n,是新手必学的算法,能解决小数据的素数判断
1、暴力枚举基本思想:
从1到n枚举每一个数,判断每个数是不是素数。质数的定义就是只能被1和自身整除的数字,例如2、3、5、7、11、13…等等,对于每一个数,我们只需要判断这个定义即可
2、模板代码
#include<iostream>
#include<cmath>//需要用到sqrt()函数
using namespace std;//判断素数
bool prime(int val){// 1-3的值需要特判,因为我们循环判断只判断到sqrt(val),1-3是判断不了的if(val==1)return 0;if(val==2||val==3)return 1;
// 为什么只要判断到sqrt(val)?
// 例如一个数8,它的因数有1、2、4、8,可以发现1<2<sqrt(8)<4<8
// 所以我们只要判断小于sqrt(8)的数就可以了,因为因数都是成对出现的for(int i=2;i<=sqrt(val);i++){// 如果被整除了,那么该数一定不是素数,返回0if(val%i==0)return 0;}
// 如果是素数就返回1return 1;
}int main(){int n;cin>>n;for(int i=2;i<=n;i++){// 如果返回值是1,那么该数是素数,输出即可if(prime(i)==1){cout<<i<<' ';}}
}
3、运行结果
输入:
100
输出:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
三、埃氏筛
埃氏筛复杂度接近O(n)*logn\log nlogn,是比较容易理解、容易学习的算法
1、埃氏筛基本思想:
如果一个数是素数,那么它的倍数就不是素数。
例如:
2是素数,那么4、6、8、10、12…都不是素数
3是素数,那么6、9、12、15、18…都不是素数
4不是素数,在2的时候已经知道4不是素数了,我们不必重复说明8、12、16…等等不是素数,因为这些数在2的时候已经可以证明它们不是素数了
5没有被2、3、4标记为它不是素数,那么就说明5不能被2、3、4整除,哪么就说明5是素数
6被在3的时候被标记为不是素数了,直接跳过
7和5一样,没有被2、3、4、5、6标记为不是素数,那么7就是素数,而14、21、28…都不是素数
…
以上就是埃氏筛的基本思想,我们模拟上面的过程即可快速求出1到n所有的素数
2、模板代码
#include<iostream>
using namespace std;
int main(){// f[i]=1代表i不是素数,f[i]=0代表i是素数 int f[100010]={1,1};int n;cin>>n;
// 埃氏筛 for(int i=2;i<=n;i++){if(f[i]==1)continue;for(int j=2;i*j<=n;j++){f[i*j]=1;}}
// 打印 for(int i=0;i<=n;i++){if(f[i]==0){cout<<i<<' ';}}
}
3、运行结果
输入:
100
输出:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
四、欧拉筛
欧拉筛又叫线性筛,可以把问题时间复杂度优化到O(n)。是求范围内素数最好用的算法
1、对比埃氏筛
埃氏筛的复杂度为什么达不到O(n)呢?因为它在标记不是素数的时候存在大量的重复操作。
例如:
12,它在2、3的时候都被标记了1次
30,它在2、3、5的时候都被标记了1次
欧拉筛的巧妙之处在于它能去掉重复的标记
2、欧拉筛的基本思想
保证每个数只被除1以外最小的质因数标记
例如:
12,它有质因数2、3,那么它只被2标记
15,它有质因数3、5,那么它只被3标记
30,它有质因数2、3、5,那么它只被2标记
实现:
(1) 需要用一个数组 p[n] 把找到的素数存下来
(2) 我们需要逆向思考,从最大的因数找到最小的质因数,例如12,我们通过6,找到质因子2,即当我们处理6的时候需要把12给标记为不是素数
(3)处理一个数时我们遍历每一个已经有的质数,当该质数是该数的因数是退出,因为对于后面的数来说,该数不是最大的因数了!这一步是有点难理解的,慢慢来,多推敲几遍
第三点理解:
例如当前的数是9,那么此时已经找出了质数2、3、5、7
遍历这些质数,那么9*2=18不是质数,9*3=27不是质数,9*5=45不是质数,9*7=63也不是质数,但实际上我们在更新完 27 之后就应该退出了,而不去更新45和63。
因为9并不是45的最大因数,15才是,即这个数在处理15的时候会被标记的,如果现在标记就会出现无用的标记了。
63也是一样的道理,它的最大因数是21,即这个数在处理21的时候会被标记。
为什么处理9的时候,3之后的5、7,最大的因数都不是9?而3和3之前最大因数都是9呢?
我们可以把3当作桥梁,因为3是9的因数,遍历5、7时,9*5可拆分为3*3*5=3*15,9*7可拆分为3*3*7=3*21,而2、3都是不可分的,29、39,最大的因数就是9,它们的数值应该在此时更新为不是素数
3、模板代码
#include<iostream>
using namespace std;
int main(){int d=0;int p[100010]={0};int f[100010]={1,1};int n;cin>>n;for(int i=2;i<=n;i++){if(f[i]==0){//如果没被标记过,那么i是质数 p[d++]=i;}for(int j=0;j<d;j++){if(p[j]*i<=n){//标记以i为最大因数的数为不是素数(除了1和本身) f[p[j]*i]=1;}if(i%p[j]==0){//如果p[j]是i的因数,那么后面的数都不是以i为最大因数的 break;}}}for(int i=0;i<d;i++){//打印1到n的质数 cout<<p[i]<<' ';}}
3、运行结果
输入:
100
输出:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
五、总结
埃氏筛的实现原理是比较简单的,使用的场景也比较广泛,但在个别的竞赛题中会卡这点时间,必须使用欧拉筛。
欧拉筛理解的过程是有点难的,但在真正理解之后思路会非常清晰,看不懂就多看两遍
加油咯!兄弟萌
c++入门必学算法 质数筛相关推荐
- c++入门必学算法 并查集
一.什么是并查集 并查集其实就是实现一个类似朋友圈的功能,朋友的朋友是朋友,朋友的朋友的朋友也是朋友,即只要有关系一些人就合并成为一个朋友圈. 并查集可以实现查询两个人是否是朋友,查询朋友圈的个数 二 ...
- ue4导入倾斜摄影_倾斜摄影入门必学|Context Capture建模软件工作流程
对于一个典型的 倾斜摄影入门必学|Context Capture建模软件工作流程www.swqy3d.com 来讲,分为了如下几步:1 新建项目后导入照片.POS.点云等数据.①导入照片 ②当你新建 ...
- [新手必备]Python 基础入门必学知识点笔记
Python 作为近几年越来越流行的语言,吸引了大量的学员开始学习,为了方便新手小白在学习过程中,更加快捷方便的查漏补缺.根据网上各种乱七八糟的资料以及实验楼的 Python 基础内容整理了一份极度适 ...
- 【笔记-java】java工程师-入门必学
路径 目录 子目录 重点 课程名 备注 java工程师 入门必学 语法基础 环境搭建.开发工具使用.基础语法 java入门第一季 面向对象 继承.封装.多态 java入门第二季 常用工具类 异常.字符 ...
- 深度学习入门必学(第三篇:循环神经网络01)
深度学习入门必学(第三篇:循环神经网络01) 一,第三篇:循环神经网络01 来自 一,第三篇:循环神经网络01
- zbrush常用笔刷_【建模】新手入门必学,ZBrush中常用笔刷简介!
原标题:[建模]新手入门必学,ZBrush中常用笔刷简介! 单击左托盘的笔刷图标,弹出一个笔刷库,其中有许多常用笔刷,这也是许多初学者所头疼的问题,zbrush的笔刷非常多,而且功能很强大,好多朋友不 ...
- 数控机床坐标的介绍,通俗易懂,新手入门必学!
数控机床坐标的介绍,通俗易懂,新手入门必学! 1.机床坐标系的定义 在数控机床上加工零件,机床的动作是由数控系统发出的指令来控制的.为了确定机床的运动方向和移动距离,就要在机床上建立一个坐标系,这个坐 ...
- 入门必学 | R语言数值型、字符型及因子型数据之间的差异与转换
字符型.数值型及因子型数据之间的转换 数据类型的基本知识 不同数据类型之间的差异 数值型与字符型或因子型绘图时的差异 数值型与因子型和字符型的模型构建时的差异 三种数据类型之间进行转换 常用的三 ...
- 外汇入门必学基础知识——基本面分析
外汇入门必学基础知识--基本面分析 基本面分析是指对影响一国经济以及货币汇率变化的核心要素进行研究,它旨在通过分析一系列经济指标.政府政策及事件,来预测某一经济周期中的汇率变化和市场趋势.基本面数据不 ...
最新文章
- 在Caffe中调用TensorRT提供的MNIST model
- CATransform3D的m34值动画
- iphone图片编辑画笔_苹果超强新功能上线!它打开了 iPhone 摄影的新大门
- [翻译] Visual Studio 2019 RC版发布
- 动态规划之-最大子段和
- 数学建模-12.预测模型
- python代码-我整理的Python代码规则
- Bossie Awards 开源大数据工具最佳列表
- spss20安装许可证代码_SPSS 22下载安装教程
- 【c4d学习笔记】对称方向不对的问题
- 如何通过看原版电影学英语
- 推荐一款办公室必备股票看盘工具
- 解决批改网写英语作文不能粘贴问题
- 原型设计工具Axure RP9下载、中文语言操作说明(赠授权码)
- python爬取问卷星内容,Python 问卷星自动填写 爬虫
- ANO Tech 匿名四轴 制作分享
- 本周大新闻|谷歌眼镜企业版正式停售;Meta重组大裁员
- 2020腾讯视频实习生面试
- 诺贝尔物理学奖揭晓:LED灯将点亮整个21世纪
- 大盘是超跌反弹还是彻底反转?