筛法

埃筛

埃拉托斯特尼筛法的缩写,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-素数筛法的更多相关文章

  1. hdu4497 GCD and LCM ——素数分解+计数

    link:http://acm.hdu.edu.cn/showproblem.php?pid=4497 如果G%L != 0,说明一定无解. 把K = G / L质数分解,G / L = p1^t1 ...

  2. 学习:数学----gcd及扩展gcd

    gcd及扩展gcd可以用来求两个数的最大公因数,扩展gcd甚至可以用来求一次不定方程ax+by=c的解   辗转相除法与gcd 假设有两个数a与b,现在要求a与b的最大公因数,我们可以设 a=b*q+ ...

  3. 【Python】2.13学习笔记 数学函数和随机函数

    我死了,今天看课看过头了,忘了发作业,被典明批评 而且化学作业还是瞎搞的,直接就发了 我觉得我已经提前死亡了,现在不死亡,开学也会的 函数 挺容易的,有很多语言之间重合的部分 注意 在使用某些数学函数 ...

  4. OI数学 简单学习笔记

    基本上只是整理了一下框架,具体的学习给出了个人认为比较好的博客的链接. PART1 数论部分 最大公约数 对于正整数x,y,最大的能同时整除它们的数称为最大公约数 常用的:\(lcm(x,y)=xy\ ...

  5. 初等数论学习笔记 III:数论函数与筛法

    初等数论学习笔记 I:同余相关. 初等数论学习笔记 II:分解质因数. 1. 数论函数 本篇笔记所有内容均与数论函数相关.因此充分了解各种数论函数的名称,定义,符号和性质是必要的. 1.1 相关定义 ...

  6. Canvas 数学、物理、动画学习笔记一

    Canvas 第五章 数学.物理和运动学习笔记让人映像深刻的运动,需要我们不只是简单的知道如何移动对象,还需要知道怎么按用户期望看到的方式去移动它们.这些需要基于数学知识的基本算法和物理学作用.基于点 ...

  7. 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记

    一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...

  8. tensorflow学习笔记(3)前置数学知识

    tensorflow学习笔记(3)前置数学知识 首先是神经元的模型 接下来是激励函数 神经网络的复杂度计算 层数:隐藏层+输出层 总参数=总的w+b 下图为2层 如下图 w为3*4+4个   b为4* ...

  9. 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 ...

随机推荐

  1. ABP Framework 研习社经验总结(6.28-7.2)

    ABP Framework 研习社经验总结(6.28-7.2) 研习社初衷 在翻译 <实现领域驱动设计>-- 基于 ABP Framework 实现领域驱动设计实用指南 时,因为DDD理论 ...

  2. ceph-csi源码分析(6)-rbd driver-nodeserver分析(下)

    更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi源码分析(6)-rbd driver-nodeserver分析(下) 当c ...

  3. 关于vim

    全部删除:按esc后,然后dG全部复制:按esc后,然后ggyG全选高亮显示:按esc后,然后ggvG或者ggVG 在win中使用<C-a>是全选,如果需要在vim中使用<C-a&g ...

  4. flex中Button事件中的e.target

    关于flex中的Button事件中的e.target. 今天想在事件中调用模块中的对象通过e.target获取单击的这个Button对象,但是可能是使用var btn:Button = e.targe ...

  5. thinkphp5.0 QQ第三方登录详解

    一.前期准备工作 到QQ互联官网进行开发资质认证,并创建网站应用.获取到appid和appkey后,下载demo文件. demo文件下载方式:QQ互联>文档资料>SDK及资源下载>p ...

  6. Python自动化之封装日志模块(一)

    ------------恢复内容开始------------ 简介: 自己也在训练营学习之中,闲来之余,自己写着玩的,主要还是为了学习,希望和前辈和大佬相互学习共进. 日志模块主要有四大组件:日志器, ...

  7. docker安装和配置nginx

    配置nginx docker配置nginx 本机ip是192.168.0.200 docker pull nginx 配置nginx主机 vi /root/docker/nginx/nginx01.c ...

  8. Linux中grep和egrep命令详解

    rep / egrep 语法: grep  [-cinvABC]  'word'  filename -c :打印符合要求的行数-i :忽略大小写-n :在输出符合要求的行的同时连同行号一起输出-v ...

  9. php弱类型比较

    前言:今天XCTF题目中出现了弱类型比较,特别过来记录一下, 0x01: == 是弱类型比较,两个不同类型比较时,会自动转换成相同类型后再比较值 ===是强比较,需要比较值和类型 0x02: 看下图案 ...

  10. ReadyAPI 测试工具和创建管理

    通过测试加速API质量APIs 和微服务正在改变组织在数字世界中开展业务的方式,对它们进行测试 比以往任何时候都更加重要 ReadyAPI测试工具是创建.管理.并运行自动化测试REST.SOAP.Gr ...