学习笔记:数学-GCD与LCM-素数筛法
筛法
埃筛
埃拉托斯特尼筛法的缩写,EraSieve (这个英文其实是为了方便做函数名不要再写shake了)
它的核心思想其实是当确认了一个数是质数以后,把它的所有倍数打上标记说这玩意不是质数。那现在的问题就只剩下怎么确定一个数是不是质数了。
原理
我们先这样想,如果一个数 \(n\) 是合数,那么一定可以表示为 \(a*b\) , 其中 \(a、b\) 都不能等于 \(1\) 和 \(n\) ,那这样的话 \(a、b\) 都一定会是小于 \(n\) 的,也就是说如果我们在\(2\sim n\) 遍历的话,只要 \(n\) 是合数,那么它一定会在遍历到它之前被筛掉(相当于是它是某个小于它的数的倍数)。那么我们只需要从 \(2\) 开始遍历,记录每一个数有没有被筛掉,如果在遍历的它的时候没有被筛过,那么它就一定是质数(相当于是它不能表示为某个小于它的数的倍数,大于它的数就更不可能)。
代码
int not_pri[MX]={0};//not_pri[i]表示i这个数是否为质数,质数为0,非质数为1
void EraSieve(int range){//筛出所有小于range的质数
not_pri[1]=0;//如果想让not_pri表示非合数,那么这里需要让not_pri[1]=1
for(int i=2;i<=range;i++){
if(not_pri[i]==0){//如果i不是质数,那么它就没有必要再翻倍,因为它的倍数必然可以表示为它的某个质因数的倍数,所以必定已经被筛过了
for(int j=2;i*j<=range;j++){
not_pri[i*j]=1;//筛除倍数
}
}
}
}
复杂度分析
时间复杂度:\(O(n\log\log n)\) (范围*质数个数)
欧拉筛
也叫线性筛,EulerSieve (还是方便的函数名)
欧拉筛其实是针对埃筛的超级优化,它们的大致想法是一样的,都是把质数的倍数打上标记来筛掉合数,埃筛的花时间主要是在筛掉倍数,我们继续想一想埃筛的遍历方式里面是不是有针对合数的倍数的剪枝,但是我们来看这样一个例子:
当\(i=2\)的时候,筛掉了\(\ \ 4,\ \ 6,\ \ 8,10,12,14,16,18\dots\)
当\(i=3\)的时候,筛掉了\(\ \ 6,\ \ 9,12,15,18,21,24,27\dots\)
你会发现,虽然我们只筛掉质数的倍数,但是在上面那个例子里,所有 \(6\) 的倍数都会被筛两遍,那如果一个数有多个质因子呢?重复筛的次数是不是更多了?是不是就造成了更多的无用循环?那么这个只根据是不是质数进行剪枝是不是可以更加精准呢?所以欧拉筛就诞生了。
让每一个数只被它最小的质因数筛到,就是欧拉筛改进后的剪枝方法,也是欧拉筛的核心思想。那具体要怎么实现呢?
原理
我们拿 \(12\) 做一个例子,按照我们埃筛的方式来,会这样反复的筛掉 \(12\) : \(2*6=3*4\) 。想办法只用\(2*6\)来筛掉 \(12\) 就可以了,我们可以发现一个数除以它最小的质因数得到的数一定是它最大的因数(\(2*6\)),而其他的表示方法一定可以分解成更小的质因数相乘的形式(\(3*4=3*2*2=2*6\)),也就是说如果一个数 \(n\) 除以一个质因数 \(x\) 得到的数 \(y\) 是一个比这个质数 \(x\) 更小的质数的倍数,那么这个质数 \(x\) 就一定不是最小的质数,自然也就不用这个质数来筛了。 结合 \(12\) 的例子来理解一下这句话:\(n=12,x=3\) 得 \(y=12 /3=4\) ,因为\(\ 4=2*2\ , \ 2<3\),所以 \(3\) 不是最小质数。
其实这样麻烦的判别方法对于单个单个的数来说肯定不是最优的(直接挨个枚举\(2\sim\sqrt{n}\)看是不是整除岂不是更简单),之所以要用这样的一个性质,是因为我们需要筛啊,筛就需要枚举倍数,所以需要找一个通过倍数的关系来确定是不是最小质因数的性质。
接着看,可以发现只要是任何一个大于 \(2\) 的质数 \(x\) 来乘上 \(4\) 得到的准备筛掉的数一定可以写成 \(2*2x\)的形式,就是说它的最小质因数肯定就不是 \(x\) 了,而是 \(2\) 了,那么就没有必要继续将之后的质数都没有必要筛掉他们的 \(4\) 倍,因为他们的 \(4\) 倍数肯定可以被 \(2\) 筛掉。更一般化的形式就是,如果正在筛掉一个质数\(x\)的\(y\)倍,而这个 \(y\) 能被一个比 \(x\) 小的质数 \(z\) 整除,所以 \(x*y\) 一定可以表示为 \(z*k\) ,而 \(z\) 是比 \(x\) 小的,回到欧拉筛的核心思想:“每一个数只被它最小的质因数筛到”,所以所有大于 \(x\) 的质数都不用筛 \(y\) 倍了,因为一定可以在筛去 \(z\) 的 \(k\) 倍时筛去。(这里可以求出来\(\displaystyle k=\frac{x*y}{z}\));
为了用上这个那我们再改一下筛的方法,埃筛的方法是通过枚举一次性把这个质数的所有倍数全部标记完,而欧拉筛是先枚举质数的乘数,每一次标记上目前所有已知质数的某个确定的倍数(比如说都筛去目前已所有质数的\(3\)倍,下一次筛去所有已知质数的 \(4\) 倍,每筛一次单个质数最多只会多一倍),这样就可以利用到上两段发现的性质来进行优化了。而这里的枚举倍数再仔细一看,其实可以利用埃筛里枚举的 \(i\) ,\(i\) 在这里有了两个意义:①当前需要判断是不是质数的数;②所有质数筛去的倍数。
代码
int pri[MX]={0};// pri[i]储存质数表,其中pri[0]表示这个质数表里有多少个数
int not_pri[MX]={0};//同埃筛里的not_pri[]
void EularSieve(int range){
for(int i=2;i<range;i++){
//i的第一个意义:判断i是不是质数,判断理由和埃筛一模一样
if(not_pri[i]==0)
pri[++pri[0]]=i;
//i的第二个意义:筛去 目前所有已知质数*i 得到的合数
for(int j=1;j<=pri[0];j++){//枚举当前已知质数
if(pri[j]*i>range)break;//超出判断范围
not_pri[pri[j]*i]=1;
//重点!
if(i%pri[j]==0)break;
//用上面一般化的形式来表述的话,x=pri[j],y=i,这里由于pri是递增的,所以就相当于是判断y能不能被更小的质因数整除
//如果i%pri[i]为0了,那么就找到了一个比x小的质数z,那么之后的倍数的最小的质因数就不再是x而是z了,所以不用接着筛了
}
}
}
复杂度分析
时间复杂度:\(O(n)\) (每个数只被筛去一次)
学习笔记:数学-GCD与LCM-素数筛法的更多相关文章
- hdu4497 GCD and LCM ——素数分解+计数
link:http://acm.hdu.edu.cn/showproblem.php?pid=4497 如果G%L != 0,说明一定无解. 把K = G / L质数分解,G / L = p1^t1 ...
- 学习:数学----gcd及扩展gcd
gcd及扩展gcd可以用来求两个数的最大公因数,扩展gcd甚至可以用来求一次不定方程ax+by=c的解 辗转相除法与gcd 假设有两个数a与b,现在要求a与b的最大公因数,我们可以设 a=b*q+ ...
- 【Python】2.13学习笔记 数学函数和随机函数
我死了,今天看课看过头了,忘了发作业,被典明批评 而且化学作业还是瞎搞的,直接就发了 我觉得我已经提前死亡了,现在不死亡,开学也会的 函数 挺容易的,有很多语言之间重合的部分 注意 在使用某些数学函数 ...
- OI数学 简单学习笔记
基本上只是整理了一下框架,具体的学习给出了个人认为比较好的博客的链接. PART1 数论部分 最大公约数 对于正整数x,y,最大的能同时整除它们的数称为最大公约数 常用的:\(lcm(x,y)=xy\ ...
- 初等数论学习笔记 III:数论函数与筛法
初等数论学习笔记 I:同余相关. 初等数论学习笔记 II:分解质因数. 1. 数论函数 本篇笔记所有内容均与数论函数相关.因此充分了解各种数论函数的名称,定义,符号和性质是必要的. 1.1 相关定义 ...
- Canvas 数学、物理、动画学习笔记一
Canvas 第五章 数学.物理和运动学习笔记让人映像深刻的运动,需要我们不只是简单的知道如何移动对象,还需要知道怎么按用户期望看到的方式去移动它们.这些需要基于数学知识的基本算法和物理学作用.基于点 ...
- 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记
一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...
- tensorflow学习笔记(3)前置数学知识
tensorflow学习笔记(3)前置数学知识 首先是神经元的模型 接下来是激励函数 神经网络的复杂度计算 层数:隐藏层+输出层 总参数=总的w+b 下图为2层 如下图 w为3*4+4个 b为4* ...
- hdu 4497 GCD and LCM 数学
GCD and LCM Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4 ...
随机推荐
- SpringBoot项目创建流程--SpringMVC
SpringBoot项目创建步骤 1. 创建SpringBoot工程 (1) File → New → Project → Spring Initilizr (2) Name:MySpringBoot ...
- 学习Qt Charts - 实时曲线
1.添加坐标轴 按照之前的一篇文章,先在工程中添加QChart.QChartView,代码如下: Dialog::Dialog(QWidget *parent) : QDialog(parent), ...
- 基于 electron 实现简单易用的抓包、mock 工具
背景 经常我们要去看一些页面所发出的请求时,经常会用到 Charles 做为抓包工具来进行接口抓取,但一方面市面是很多抓包工具都是收费或者无法二次开发的.当前我们团队大多数用的也都是 Charles, ...
- 乘风破浪,Windows11官方原装4K壁纸,前卫的艺术数字设计
Windows11预览版官方壁纸 默认主题Windows Windows.zip 月轮主题ThemeA ThemeA.zip 艺术石主题ThemeB ThemeB.zip 日升主题ThemeC The ...
- 第13章:Kubernetes 鉴权框架与用户权限分配
1.Kubernetes的安全框架 访问K8S集群的资源需要过三关:认证.鉴权.准入控制 普通用户若要安全访问集群API Server,往往需要证书.Token或者用户名+密码:Pod访问,需要Ser ...
- 7、resync实时备份
sersync+rsync(增量,无差异备份),resync支持多线程,效果比inotify更好,配置思想和inotify很相似 7.1.在备份服务器上安装并配置rsync服务,实现nfs共享目录,可 ...
- Linux从头学02:x86中内存【段寻址】方式的来龙去脉
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- WEB应用访问缓慢的问题定位
WEB应用访问缓慢的问题定位 欢迎关注博主公众号「java大师」, 专注于分享Java领域干货文章, 关注回复「资源」, 免费领取全网最热的Java架构师学习PDF, 转载请注明出处 http://w ...
- hdu 6050 Funny Function 矩阵快速幂
就算告诉我是矩阵快速幂我也推不出递推式呀!!! 官方题解: 对于任意i>=1,当j>=3时,有通过归纳法可以得到 进而推导出 后来自己重新推导了一遍 #include <iostre ...
- 利用ONT测序检测真核生物全基因组甲基化状态
摘要 甲基化在真核生物基因组序列中广泛存在,其中5mC最为普遍,在真核生物基因组中也有发现6mA.捕获基因组中的甲基化状态的常用技术是全基因组甲基化测序(WGBS)和简化甲基化测序(RRBS),而随着 ...