简单来说,逆元就是求 ${1\over a}\bmod p$,其中 $\gcd(a,p)=1$。

形式化的说,我们要求同余方程 $ax\equiv1\pmod p$ 的解。

求解这类问题一般有三种方法:扩展欧几里得、费马小定理、线性算法。

费马小定理

当 $\gcd(a,p)=1$ 且 $p$ 为质数时,$x=a^{p-2}$。

对于 C++ 而言,快速幂即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
using ll=long long;
ll qpow(ll a,ll b){
ll res=1;
while (b){
if (b&1) res=(res*a)%mod;
b/=2;
a=(a*a)%mod;
}
return res;
}
ll inv(ll a){
return qpow(a,mod-2);
}

扩展欧几里得

1
2
3
4
5
6
7
8
9
10
11
12
13
using ll=long long;
tuple<ll,ll> xgcd(ll a,ll b){ // b 是模数
ll mod=b;
ll s0=1,s1=0;
while(b!=0){
ll q=a/b;
a-=q*b;
s0-=q*s1;
swap(a,b);
swap(s0,s1);
}
return {a,(s0+mod)%mod}; // 最大公约数(在求逆元时一定是 1) 逆元
}

Python 的逆元

Python 的 pow 运算符是基于快速幂的,并且其实 pow 支持模数,所以如果你要求
$$
a^b\bmod p
$$

你可以

1
pow(a,b,p)

那么不难想到,使用费马小定理求逆元在 Python 中可以

1
pow(a,p-2,p)

但其实 pow 函数直接支持负数,所以可以直接

1
pow(a,-1,p)

这种 pow 也不受 $p$ 为质数这一条件的约束,只需要满足 $\gcd(a,p)=1$ 即可。