数学基础-同余
同余式
若两个整数 \(a, b\) 模 \(m\) 的余数相同,则称 \(a, b\) 模 \(m\) 同余,记为 \(a \equiv b \pmod{m}\)。
费马小定理
若 \(p\) 为质数,且 \(a, p\) 互质,则 \(a^{p-1} \equiv 1 \pmod{p}\)。
欧拉定理
若 \(a, m\) 互质,则 \(a^{\varphi(m)} \equiv 1 \pmod{p}\),其中 \(\varphi(\cdot)\) 为欧拉函数。
扩展欧拉定理/欧拉降幂公式
威尔逊定理
任意一个大于 \(1\) 的数 \(p\) 是质数的充要条件为:
\(p>1, (p-1)!\equiv -1 \pmod{p} \Leftrightarrow p\in\mathbb{P}\)
推论
- 若 \(p\) 是质数,则\((p-1)!+1 \equiv 0 \pmod{p}\)
- 若 \(p\) 是大于 \(4\) 的合数,则 \((p-1)!\equiv 0\pmod{p}\)
乘法逆元
若 \(a, b\) 互质,且满足同余方程 \(ax \equiv 1 \pmod{b}\),则称 \(x\) 为 \(a\) 模 \(b\) 的乘法逆元,记作 \(a^{-1}\)
最大公约数
欧几里得算法/辗转相除法
递归求解,核心代码如下:
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
对于 C++17,可使用 <numeric>
头中的 std::gcd
与 std::lcm
来求最大公约数和最小公倍数。
裴蜀定理
推广1
推广2
若 \(a_i<0\),则可带入 \(|a_i|\)。
扩展欧几里得算法
求不定方程 \(ax+by=\gcd(a,b)\) 的一组整数解。
(1) 当 \(b=0\) 时有 \(ax=a\),故 \(x=1, y=0\)。
(2) 当 \(b\ne0\) 时,
由欧几里得算法,\(\gcd(a,b)=\gcd(b,a\bmod b)\)。
由裴蜀定理,有
故 \(x=y_1, y=x_1-\lfloor\frac{a}{b}\rfloor y_1\),可递归求解出特解 \((x_0, y_0)\),然后根据 \(ax+by=0\) 构造通解:
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
求不定方程 \(ax+by=c\) 的一组整数解。
根据裴蜀定理,对 \(c\) 进行分类讨论:
(1) 若 \(\gcd(a,b)\mid c\),则有整数解。先用扩欧算法求出 \(ax+by=\gcd(a,b)\) 的解,再乘上 \(\frac{c}{\gcd(a,b)}\),即可得原方程的特解,最后根据 \(ax+by=0\) 构造通解。
(2) 若 \(\gcd(a,b)\nmid c\),则无整数解。
求同余方程 \(ax\equiv b\pmod{m}\) 的一组整数解。
(1) 先将同余方程转化为不定方程,由 \(ax\equiv b\pmod{m}\) 得 \(ax\equiv m(-y)+b\) 即 \(ax+my=b\)。
(2) 根据裴蜀定理,当 \(\gcd(a,m)\mid b\) 时有整数解,否则无整数解。若有整数解,则用扩欧算法先求出 \(ax+my=\gcd(a,m)\) 的解,再乘上 \(\frac{b}{\gcd(a,m)}\) 得原方程的特解。
乘法逆元
定义
若正整数 \(a,p\) 互质,且 \(ax\equiv 1\pmod{p}\),则称 \(x\) 为 \(a\) 模 \(p\) 的乘法逆元,记作 \(a^{-1}\)。
求一个数的乘法逆元。
(1) 若 \(p\) 是质数,则由费马小定理有 \(a\times a^{p-2}\equiv 1\pmod{p}\),故只需用快速幂求 \(a^{p-2}\) 即可。
(2) 若 \(p\) 不一定是质数,则由可通过求解同余方程 \(ax\equiv 1\pmod{p}\),用扩欧算法求 \(x\) 即可。
线性逆元递推公式
求 \([1,n]\) 多个数的模 \(p\) 逆元。
首先 \(1^{-1}\equiv 1\pmod{p}\),令 \(p=k\times i+r, (1<r<i<p),k=\lfloor\frac{p}{r}\rfloor,r=p-\lfloor\frac{p}{r}\rfloor\times i=p\bmod i\),由 \(k\times i+r\equiv 0\pmod{p}\),则 \(i\equiv -k^{-1}r\pmod{p}\),故有:
若用 \(inv[i]\) 表示 \(i\) 的模 \(p\) 逆元,则递推公式为 \(inv[i]=(p-\lfloor\frac{p}{i}\rfloor)\times inv[p\%i]\%p\)。从 \(1\) 到 \(n\) 依次求模 \(p\) 逆元即可,时间复杂度为 \(O(n)\)。
求 \([1!,n!]\) 多个数的模 \(p\) 逆元。
若用 \(fac\_inv[i]\) 表示 \(i!\) 的模 \(p\) 逆元,可先求出 \(n!\) 的模 \(p\) 逆元 \(fac\_inv[n]\)。由 \(n!\times fac\_inv[i]\equiv 1\pmod{p}\) 和 \(n!=n(n-1)!\),可得 \((n-1)!\) 的模 \(p\) 逆元 \(fac\_inv[n-1]=n\times fac\_inv[n]\%p\)。从 \(n!\) 到 \(1!\) 依次求模 \(p\) 逆元即可,时间复杂度为 \(O(n)\)。
注意事项
运算时取模
- 加法:\((a+b)\%p\)
- 减法:\(((a-b)\%p+p)\%{p}\)
- 乘法:\((a\times b)\%p\)
- 除法:\((a\times inv(a))\%p\),其中 \(inv(a)\) 为 \(a\) 的乘法逆元。
向上取整
C++
是整除时默认向 \(0\) 取整。
\(\forall a,b\in N_{+}, \lceil\frac{a}{b}\rceil=\frac{a+b-1}{b}\)