这里会简单记录我学习的基础数论。这里的证明可能都不大严谨,仅供参考。
欧几里得算法
如果我们想要求 $gcd(a,b)$ ,最简单的方式便是枚举,但这太慢了。
于是我们有了我们的辗转相除法,也就是欧几里得算法,它可以在 $O(log(a+b))$ 的复杂度内求出 $gcd(a,b)$ 。
$$\forall a,b \in \mathbb{N}, b \not = 0,\quad gcd(a,b) = gcd(b,a\bmod b)$$
证明
$a < b$ 时
$gcd(b,a \bmod b)=gcd(b,a)=gcd(a,b)$
$a \geq b$ 时
设 $r=a\bmod b$ ,$d$ 为 $a,\,b$ 任意一个公约数。
则 $a=kb+r,\;a\equiv b\equiv 0 \pmod{d}$
$\therefore a-kb\equiv r \equiv 0 \pmod{d}$
$\therefore d\,|\,b,\,d\,|\,a\bmod b$
所以 $a,b$ 和 $b, a \bmod b$ 的公约数集合是相同的,它们的最大公约数必然也相等。
$\therefore gcd(a,b)=gcd(b, a \bmod b)$
要注意边界:$b = 0$ 时,$gcd(a,b) = a$
代码
1 | int gcd(int a, int b) |
拓展欧几里得
拓展欧几里得用于在已知自然数 $a,b$ ,求解 $ax+by=gcd(a,b)$ 的 $(x,y)$ 的整数解时。
$ax+by=gcd(a,b)$
$=gcd(b,a\bmod b)$
$\Rightarrow bx+(a\bmod b)\,y$
$=bx+(a-\lfloor\dfrac{a}{b}\rfloor\,b)\,y$
$=ay+b\,(x-\lfloor\dfrac{a}{b}\rfloor\,y)$
所以 $x$ 变成了 $y$ , $y$ 变成了 $x-\lfloor\dfrac{a}{b}\rfloor\,y$
于是我们可以愉快地递归求解。这里也需要注意边界: $b=0$ 时,$a=1,\,ax+by=1$ ,因此 $x=1,y=0$ 。
代码
1 | void exgcd(int a, int b, int &x, int &y) |
乘法逆元
当我们想要求形如 $\dfrac{a}{b} \bmod p$ 的值的时候,就需要用到乘法逆元。
逆元定义
若 $a \times x \equiv 1 \pmod{b}$ ,且 $a \perp b$ ,则我们定义 $x$ 为 $a$ 的逆元
所以对于 $\dfrac{a}{b} \bmod p$ ,我们就可以求出 $b$ 在 $\bmod p$ 意义下的逆元 $x$ ,原分数的值便可以表示为 $a \times x \bmod{p}$
求解逆元的方法
拓展欧几里得
这个我们刚刚讲过。这种做法就是将 $a \times x \equiv 1 \pmod {b}$ 转换为 $a \times x + b \times y = 1 $ ,然后求解。
代码
1 | void exgcd(int a, int b, int &x, int &y) |
快速幂
费马小定理:若 $p$ 为质数, $a$ 为正整数, 且 $a \perp p$ ,则有 $a^{p-1} \equiv 1 \pmod{p}$
所以我们可以进行推导:
$a \times x \equiv 1 \equiv a^{p-1} \pmod{p}$
$x \equiv a^{p-2} \pmod{p}$
因此我们可以用快速幂求出 $a^{p-2} \pmod{p}$ 的值,这个数就是 $a$ 的逆元了。
代码
1 | int qpow(int a, int b, int p) |
线性递推
这个可以用来求一连串数对于$\bmod p$ 的逆元。
首先我们知道 $1^{-1} \equiv 1 \pmod{p}$
设 $k = \lfloor\dfrac{p}{i}\rfloor,\,r = p \bmod{i}$
$k \times i + r \equiv 0 \pmod{p}$
两边同时乘上 $i^{-1},\,r^{-1}$
$k \times r^{-1} + i^{-1} \equiv 0 \pmod{p}$
$i^{-1} \equiv -k \times r^{-1} \pmod{p}$
$i^{-1} \equiv -\lfloor\dfrac{p}{i}\rfloor \times (p \bmod{i})^{-1} \pmod{p}$
于是我们可以从前推出当前的逆元。
代码
1 | inv[1] = 1; |
阶乘逆元
这个一般在求组合数的值得时候用到。比较简单,就一笔带过了。
一般求 $1\sim n$ 的阶乘逆元有两种方法:
- 先求出 $1\sim n$ 每个数的逆元,然后正推: $(i!)^{-1} \equiv (i - 1)! ^ {-1} \times i ^ {-1} \pmod{p}$
代码
1 | inv_fac[1] = 1; |
- 先求出 $n$ 的阶乘逆元,然后倒推: $(i!)^{-1} \equiv (i + 1)! ^ {-1} \times (i + 1) \pmod{p}$
代码
1 | inv_fac[n] = inv(fac[n]); |
欧拉函数
$$\varphi(n) = \sum\limits_{i=1}^{n-1} [n \perp i]$$
通俗的来讲, $\varphi(n)$ 表示小于 $n$ 的正整数当中有多少个数与 $n$ 互质,特别的,我们规定 $\varphi (1)=1$
这里我们有一个欧拉函数的计算公式;
$$\varphi(n) = n \times \prod\limits_{p\,|\,n}(1-\dfrac{1}{p})$$
证明先咕一会儿,有时间再写。