乘法逆元
乘法逆元
乘法逆元可以求出 $ \displaystyle {\frac {a}{b}} $ 在取模 \(P\) 的意义下的数值。
逆元
若 \(a * x \equiv 1 \pmod q\) ,且 \(a\) 与 \(b\) 互质,那么我们定义: \(x\) 为 \(a\) 的逆元,记作 \(a^{-1}\) ,也可以称 \(x\) 为 \(a\) 在 $ \pmod p$ 意义下的倒数。
对于 \(\displaystyle {\frac {a} {b}} \pmod p\) ,它的值为 \(a * b^{-1} \ \ mod \ \ p\) 。
求解逆元
快速幂
费马小定理
若 \(p\) 为素数,\(a\) 为正整数,且 \(a、p\) 互质。则有 \(a^{p-1} \equiv 1 \pmod p\) 。
若 \(x\) 为 \(a\) 的逆元,则:
所以我们可以使用快速幂求出 \(a^{p-2} \pmod p\) 的值,即为 \(a\) 的逆元。
int qmi (int a, int k, int mod)
{
int res = 1;
while (k)
{
if (k & 1) res = 1ll * a * res % mod;
a = 1ll * a * a % mod;
k >>= 1;
}
return res;
}
拓展欧几里得
在模数不为质数时,不能使用费马小定理,但是可以使用拓展欧几里得求逆元,参考此处。
线性算法
线性算法可以求出连续数字 \(1 \sim n\) 对于 \(\pmod p\) 的逆元。
首先有 \(1^{-1} \equiv 1 \pmod p\)。
假设现在要求 \(i\) 的逆元,显然 \(p = \lfloor{\dfrac p i}\rfloor * i + p \% i\) 。
那么,在模 \(p\) 的情况下:
注意到 \(p \% i\) 一定是小于 \(i\) 的,这样我们就可以从前面推出后面了。
时间复杂度:$ O(n) $
inv[1] = 1;
for (int i = 2; i <= n; i ++ )
inv[i] = (p - p / i) * inv[p % i] % p; // 取模意义下 -a = p - a
阶乘逆元
根据阶乘递推关系:
所以我们也可以先求出 \(n!\) 的逆元,再逆推,就可以得到 \(1! \sim n!\) 的逆元。
递推式: \(inv[i+1] * (i+1) = inv[i]\)
最后可以使用 \(\displaystyle {\frac{1}{i!}} * (i-1)! = \frac{1}{i}\) 。
时间复杂度为 \(O(n)\) 。