Skip to content

定义 ​

如果整数a, x满足ax≡1(mod p), 则将x称为a mod p的模逆元, 记作a−1.

模逆元也叫模倒数, 可以理解为模p同余式中a的倒数即1a, 也就是说, 模p的条件下, a和x是等价的。相似的有一些简单的性质如(ab)−1≡(a)−1∗(b)−1(mod p),(ba)−1≡ab(mod p) ,1−1≡1(mod p).

注意, a在模p条件下存在逆元的充分必要条件是, a与p互素。

意义 ​

当我们要求(ba)modp, 且b数值过大无法直接存储在变量中与a运算, 这时就可以使用乘法逆元。

由乘法逆元定义有bax≡b(mod p)⟺bx≡ba(mod p)。

求法 ​

扩展欧几里得算法 ​

过程 ​

已知, 扩展欧几里得算法可用于求ax+by=gcd(a,b)的一组可行解, 而当a、b互质时, ax+by=gcd(a,b)⟺ax+by=1⟺ax≡1(mod b)。

代码实现 ​

python

python
def exgcd(a, b):
    if b == 0: 
        return 1, 0
    x, y = exgcd(b, a % b)
    return y, x - y*(a // b)
ans = (exgcd(a, p)[0] % p + p) % p # 求a关于p的逆元

费马小定理 ​

费马小定理可用于在p为素数时互质的情况下求amodp的逆元。

过程 ​

由费马小定理, 当p为素数且a、p互质时, ap−1≡1(modp), 而a和a的逆元x满足ax≡1(modp), 即ap−1≡ax(modp)⟺x≡ap−2(modp).

所以在满足上述条件时, a(mod p)的逆元即为ap−2(modp), 使用快速幂计算即可。

python

代码实现 ​

python
def quick_pow(a, n, p):
    ans = 1
    while n:
        if n & 1:
            ans = ans * a % p
        a = a * a % p
        n >>= 1
    return ans
ans = quick_pow(a, p - 2, p) # 求a关于p的逆元

线性求逆元(递推) ​

递推法用于求[1, a]区间的每个数mod p的逆元。

过程 ​

p%a=p−a⌊pa⌋ \

⇒p%a≡−a⌊pa⌋(mod p) \

⇒a≡(p%a) / (−⌊pa⌋)(mod p)\

⇒a−1≡−⌊pa⌋(p%a)−1(mod p)\

所以有递推式inv[n]≡−⌊pn⌋∗inv[p%n] (mod p); 而对于始项1,事实上, 对于任意整数p, 都有1∗1≡1(mod p) .

代码实现 ​

c++

cpp
inv[1] = 1;
for (int i = 2; i <= n; ++i) {
  inv[i] = (long long)(p - p / i) * inv[p % i] % p;
}

参考 ​

乘法逆元的几种计算方法 | Menci's OI Blog

乘法逆元 - OI Wiki (oi-wiki.org)

乘法逆元详解 - MJT12044 - 博客园 (cnblogs.com)