2023/09/08 upd:添加了总结。
数论总结
没活了。写点笔记。
本文md源码全长超过25KB、750行,除非有时间并不建议完整阅读而是通过Ctrl+F查找想阅读的部分
取模运算
定义
在带余除法下,
整除性与约数
对于任意自然数
根据约定,
最大公约数
定义两个数
一般而言
proof:对于任意
求
互质
定义
一些常用性质:
扩展欧几里得算法
扩展欧几里得算法,简称exgcd,用于求解形如
我们先看一个更弱的问题:求
首先当
否则设
那么根据
把方程改写成
此时我们就得到了一组解,即
我们发现这恰好是一个递归的问题,所以可以很轻易地编程解决。
由于辗转相除在
1 | typedef std::array<int,2> pii; |
上面的写法比较非主流,下面是主流写法
1 | inline void exgcd(int a,int b,int &x,int &y){ |
裴蜀定理
现在我们来解决更一般的原问题。
首先
同时,我们也得出方程有解的充要条件:
上式就是裴蜀定理。
质数
定义一个正整数
前
(若无特殊说明,下文均用
不是质数的数被称为合数。合数
质数是构成所有整数的基本元素。任意整数
常用结论
数
合数
证明显然。
唯一分解定理
有且仅有一种将数分解为若干质数乘积的方案。
proof:用归纳法。
否则设
设
否则易证
证毕。
质因数分解
我们将数写作形如
这样写的好处在于有一些比较好的性质,如
利用常用结论,单次质因数分解的时间复杂度是
无穷质数定理
质数的个数是无限的。
proof:用反证法。
设
那么要么
证毕。
Mersenne数
Mersenne数指形如
但是这个东西在 OI 中并没有什么卵用。
质数的密度
这里不加证明地给出
基本筛法
如果我们要求出
倍数筛
我们将每一个数的所有倍数都标记为合数,剩下的就都是质数了。
运算次数约在
埃氏筛
倍数筛有大量的冗余标记,因为已经是合数的数的倍数会再次被标记。
我们考虑只用质数去标记合数,这样就可以大大减少冗余计算。
时间复杂度
欧拉筛(线性筛)
埃氏筛仍然会出现冗余标记。更具体的,一个数会被它的每一种因子都标记一遍。我们希望每个数只被标记一次。
我们可以考虑每个数都只被其最小质因子标记一遍(因为一个数的最小质因子乘剩余部分可以唯一确定一个属),于是我们考虑存储每个数的最小质因子
考虑枚举这个“剩余部分”。遍历到
这样可以保证每个数只被它的最小质因子标记过,时间复杂度线性。
(实现时可能不会记录
1 | const int M=1e8; |
阶乘
定义
可以看出阶乘是以极快速度增长的。
我们可以在
阶乘的质因数分解
我们显然无法对阶乘的结果直接质因数分解。如果对阶乘的每一项都分别进行质因数分解的时间复杂度也是
我们运用反演的思想,转而统计每个质因子的贡献。
如果我们将不同指数的质数分开计算,
因此每个质数
这样一来时间复杂度就降到
常见函数
积性函数
如果函数
欧拉函数
定义欧拉函数
欧拉函数是一个积性函数。
proof:对于任意
易证
推论:
proof:
莫比乌斯函数
定义莫比乌斯函数
莫比乌斯反演
常用结论:
证明这玩意可以用二项式定理或迪利克雷卷积,限于篇幅不再赘述。
莫比乌斯反演的技巧在于抓住待求式中的
积性函数与线性筛
可以在筛
以
同余
(本节中
定义
OI 中为了避免精度问题,大部分计数题都会要求输出答案对某个模数
基本性质
加减乘运算在同余运算中不受影响,换言之
因此如果涉及除法运算,我们需要引入乘法逆元。
乘法逆元
定义
容易发现
引入乘法逆元之后,我们就可以将
下文“逆元”均指代乘法逆元。
exgcd的同余形式
exgcd也可以用于求解一元一次同余方程:
proof:将
用exgcd求解逆元
我们发现实质上就是要求解
1 | int inv(int a,int p){ |
逆元的存在性
根据裴蜀定理,此方程有解当且仅当
费马小定理
对于质数
考虑
由于
证毕。
费马小定理求逆元
由于
那么我们就可以使用快速幂求出
补充:费马小定理的另一种证明
数形结合。
我们建一张图,结点为
那么根据抽屉原理,我们从任何一个数出发,在绕
由于
这也就说明了这个图是由环构成的。我们接下来需要证明环的长度为
我们设
那么我们可以推出两条限制:
所在环上的所有数都不在 所在环上。 所在环上的每个数 与 上每个数同余且一一对应(比如在 出发走三步再 与从 出发走三步结果一样,即乘法交换律)。
因此我们推出所有环环长必须相等。
再加之每个数一定在一个环上(否则可以一直连边直到回来),因此环长必定是
证毕。
威尔逊定理
proof:求解方程
中国剩余定理
中国剩余定理(Chinese Remainder Theorem,CRT)是一种用于求解线性同余方程组的算法。
由于阉割版原版CRT较为难以理解,下文将仅介绍与原版CRT除了名字没有一分钱关系的exCRT算法。它更短、适用范围更广且更加容易理解。如果您想了解原版CRT请左转OI-Wiki。
求下列方程的最小解(或模
我们首先把
把方程写作二元一次不定方程的形式:
exCRT的核心思想是归纳,即考虑如何利用前
因此我们只需要考虑只有两项的情况。我们假设要解这个方程:
时间复杂度
欧拉定理与拓展欧拉定理
欧拉定理
欧拉定理本质上是费马小定理的拓展。
欧拉定理:如果
证明:仍然考虑用建图的方式理解。
由于
由于互质等价于有逆元,那么在模
然后和费马小定理的证明一样的讨论就好了。
必成倍数性质
若
分解质因数后证明显然。
扩展欧拉定理
proof:
将
那么有
根据欧拉定理,
而根据前文所述的必成倍数性质,
CRT 合并即可。
拓展欧拉定理一般用于求解大指数幂。
乘法逆元的其他求法
线性求逆元
我从来不用
存在线性求出
线性求 个数的逆元
我们可以在
设序列为
设
我们可以用线性时间求上面的三个量,然后用
由于
离散对数问题
求解:
BSGS
大步小步(Baby Step Giant Step,BSGS)算法是一个能在
首先解决质数的情况。根据欧拉定理,如果有解一定存在
我们设
我们可以将所有的
我们发现这个数据结构需要插入和查询一个数是否存在,哈希表完美契合这个需求,这两种操作都是
最终时间复杂度
exBSES
接下来我们解决
当
考虑把原式改写成 exgcd 的形式:
当
此时相当于要求解子问题
如果此时
最终答案要加上
根据必成倍数性质,
质数检测与质因数分解的加速
朴素的质数检测是
这一节介绍两种算法用于加速质数检测和质因数分解。
Miller-Rabin 质数检测
Miller-Rabin(下文简称 MR)是一个质数检测算法,可以做到
二次探查定理
proof:
算法流程
我们基于两个逆否命题:
- 费马小定理的逆否命题:
(记为条件一) - 二次探查定理的逆否命题:
(记为条件二)
我们重复以下步骤
- 设
(其中 是奇数),并选取底数 。 - 若
,终止检测并返回不通过。(条件一) - 我们枚举
,若 ,终止检测并返回不通过。(条件二) - 优化:若
,则后续的 的结果均为 ,直接返回通过检测。
- 优化:若
底数选取技巧
- 对于
int
类型的整数,我们进行 次检测,选取前 个质数作为底数。 - 对于
long long
类型的整数,我们进行 次检测,选取前 个质数作为底数。
这样选取可以保证最终结果绝对正确(详见OEIS A014233)。
不过需要注意,质数
Pollard-Rho
Pollard-Rho
算法是一种基于随机的高效的质因数分解算法,可在期望时间复杂度
生日悖论
在
思想
首先调用 MR 判断待分解的数
设
流程
现在我们考虑如何快速判断某个生成的数与之前出现过的数同余。
我们选取任意一个函数
此时我们设想一下在序列
- 大
:由于 的值只与 有关,那么 一旦重复就会进入循环,这个过程类似一个 " " 形。 - 小
:同理, 的值也一定是一个 形。
根据生日悖论,如果
我们使用弗洛伊德判环法:我们使用两个指针
如果
- 如果此时
,说明与此同时 在大 上也追上了 ,接下来无论怎么追结果都是一样,放弃现有的 并重新生成。 - 否则我们就找到了满足条件的两个数,退出循环。
这种判环法最坏会执行小
总结
数论作为 OI 中最考验思维的部分之一,其灵活性和复杂程度导致了它成为了许多思维能力不好的选手(包括我)一座绕不去的大山。
这次写笔记虽然花了不少时间,但是写完之后去练题还是实打实感受到了自己思维的提升,对一些新手期只能背板子的算法的理解也加深了不少。
数论由于较为繁杂,大量刷题反而提升不大,练多不如练精,做数论题一定要多思考,对于特别重要的思维模型(如转化为 exgcd 是许多算法的基础)要予以积累。
虽然 OI 不考证明,但是数论的证明过程中往往蕴含在整个 OI
中都非常重要的思想(如 exgcd 和 exBSGS 的递归思想,exCRT
中的归纳思想,阶乘分解质因数中的反演思想,BSGS
的根号分治与双向搜索思想,
部分参考资料
- 《具体数学》,Graham、Knuth、Patashnik著
- OI-Wiki