传送门 -> 数论基础学习笔记(一)
在上一篇学习笔记中,我们主要涉及了 gcd、lcm、快速幂、筛法和分解质因数 的相关内容。
接下来,首先学习如何解线性同余方程和线性不定方程,之后学习费马小定理和欧拉定理,并学习求逆元的多种方法。
先从扩展欧几里得算法开始。
【扩展欧几里得算法】
欧几里得算法在求出两数最大公约数的同时,还可以顺带着解出不定方程$ax + by = gcd(a, b)$的一组解,并且在此前提下使得$|x| + |y|$取最小值。
该不定方程与同余方程$ax \equiv gcd(a, b)\pmod{b}$等价,所以必然有解。
首先直接给出代码感受一下。
【代码】
void exgcd(int a, int b, int &d, int &x, int &y) {
if (!b) d = a, x = 1, y = 0;
else exgcd(b, a % b, d, y, x), y -= x * (a / b);
}
【证明】
我们尝试采用类似数学归纳的方式证明一下该算法的正确性。
首先在算法的终止状态 $$ a * 1 + 0 * 0 = a = gcd(a, 0) $$ 是显然正确的。
设我们正在求解方程 $ ax + by = gcd(a, b) $ 的一组解 $x_1, y_1$。
此时我们已经求得了方程 $bx + (a % b)y = gcd(a, b) $的一组解$x_0, y_0$。
即 $$ bx_0 + (a % b)y_0 = gcd(a, b) $$
我们知道 $$ a % b = a - b \lfloor \frac a b \rfloor $$
直接代入,得
$$ \begin{align*} gcd(a, b) &= bx_0 + (a - b \lfloor \frac a b \rfloor)y_0 \\ &= bx_0 + ay_0 - b \lfloor \frac a b \rfloor y_0 \\ &= ay_0 + b(x_0 - \lfloor \frac a b \rfloor y_0) \\ \end{align*} $$
所以我们就有 $$ x_1 = y_0, y_1 = x_0 - \lfloor \frac a b \rfloor y_0 $$
证毕。
【线性同余方程与不定方程】
形如 $ ax \equiv b \pmod{p} $ 的方程称为不定方程。
性质(不证):该方程有解 当且仅当 $ gcd(a, p) \mid b $,且解数为$gcd(a, p)$。
该同余方程与不定方程$ ax = py + b $同解,这一点显然。
我们已经学会了使用扩展欧几里得算法解形如$ax + by = gcd(a, b)$的方程。
那么一般的不定方程该怎么解呢?
【求不定方程的一组解】
对于一个一般的不定方程 $ax = py + b$,首先移项,得 $ax - py = b$。
判断是否有 $gcd(a, p) \mid b$,若没有,则无解,若有,则设 $c = b / gcd(a, p)$。 使用扩展欧几里得算法解出方程 $ax' + py' = gcd(a, p)$ 的解 $x', y'$ 那么原方程对应的一组解为 $x = x'c, y = -y'c$ 。
【从一解到通解】
上述过程只求出了方程的一组解,那么其他的怎么办呢?
首先给出结论感受一下:
设方程 $ax + by = c$的一组解为 $(x_0, y_0)$,那么其通解为$(x_0 + kb', y_0 - ka')$,其中 $a' = a / gcd(a, b), b' = b / gcd(a, b)$,$k$ 取任意整数。
证明如下:
一般的,设方程 $ax + by = c$ 的一组解 $(x_0, y_0)$
设任意另外一组解 $(x_1, y_1)$。 则有 $$ ax_0 + by_0 = ax_1 + by_1 $$
移项,得 $$ a(x_1 - x_0) = b(y_0 - y_1) $$
设 $gcd(a, b) = g$ ,方程两边同除以 $g$ ,得 $$ a'(x_1 - x_0) = b'(y_0 - y_1) $$ 其中 $a' = a / g, b' = b / g$ 。
注意到此时 $a',b'$ 互质,所以必然有 $$ b'\mid(x_1 - x_0)$$ 那么设 $(x_1 - x_0) = kb'$,代入原方程,化得 $$ y_1 - y_0 = ka' $$
故有 $x_1 = x_0 + kb', y1 = y_0 - ka'$。
证毕。
【费马小定理和欧拉定理】
费马小定理和欧拉定理是数论中的两个重要定理。
【费马小定理】
设有质数$p$和满足$gcd(a, p) = 1$的$a$,那么 $$ a^{ (p - 1) } \equiv 1 \pmod{p} $$
【欧拉定理】
若$gcd(a, n) = 1$,那么 $$ a^{\phi(n)} \equiv 1 \pmod{n}$$
其中$\phi(n)$为欧拉函数,表示不超过n且与n互质的正整数的个数,
可以看出,费马小定理是欧拉定理的特殊情况。
这两个定理在此就不证明了。
【逆元】
若$ab \equiv 1 \pmod{p}$,则称 $b$ 为 $a$ 的逆元,记作 $b = a ^ {-1}$。
逆元存在当且仅当 $gcd(a, p) = 1$,对应了 该同余方程 有解,前面已经说明过了。
重点是逆元的各种计算方法。
借助费马小定理和欧拉定理
这两个定理都是与1同余的形式,因此可以用来计算逆元。
一般题目中会保证模数为质数,此情况下逆元必然存在,可以用费马小定理来计算。
// 当模数为质数时
inline int inv(int x){
return fastPowMod(x, MOD - 2);
}
实践中,一般不用欧拉定理计算逆元。
借助扩展欧几里得算法
求逆元的过程实际上就在是解同余方程 $ax \equiv 1 \pmod{p}$ 。
直接上扩欧就好了。
inline int inv(int num){
int d, x, y;
exgcd(num, q, d, x, y);
return ((x % MOD) + MOD) % MOD;
}
单个逆元推荐用这种方法,常数更小。
预处理逆元
逆元有一种递推方法,可以预处理 $[1, n]$ 的每个数逆元,复杂度 $O(n)$。
考虑模数 $P$ 与当前数 $i$ 的关系,写成这样的形式: $$ P = ki + r$$ 其中$k = \lfloor \frac P i \rfloor, r = P % i$。
那么有 $$ ki + r \equiv 0 \pmod P $$
左右同乘 $ (r^{-1}i^{-1}) $,得
$$ kr^{-1} + i^{-1} \equiv 0 \pmod P$$
移项,得
$$ i^{-1}\equiv -kr^{-1} \pmod P$$
也就是 $$ i^{-1} \equiv - \lfloor \frac P i \rfloor (P % i)^{-1} \pmod P$$
边界 $$ 1 ^ {-1} \equiv 1 \pmod P$$
代码:
int inv[MAXN + 1];
inline int initInv(int n){
v[1] = 1;
for(int i = 2; i <= n; i++) v[i] = v[P % i] * (P - P / i) % P;
}
预处理阶乘逆元
预处理 $[1, n]$ 中每个数阶乘的逆元,复杂度 $O(n)$。
$$ n(n!)^{-1} = ((n - 1)!)^{-1} $$ 正确性显然。
代码:
int facInv[MAXN + 1];
inline void initFacInv(int n){
int fac = 1;
for(int i = 1; i <= n; i++) fac = mulMod(fac, i);
facInv[n] = inv(fac);
for(int i = n; i; i--) facInv[i - 1] = mulMod(facInv[i], i);
}
【结语】
数论最基础的东西就写这些吧,足够基础了...... 还会有《数论进阶》的QwQ ......