常用的求逆元的方法有扩展欧几里得和费马小定理, 因为扩展欧几里得我还不会, 这里介绍一下费马小定理。
逆元的定义
有正整数 a a a和质数 p p p,满足 a x % p = 1 ax\%p=1 ax%p=1的最小正整数 x x x就称为是 a a a的逆元
逆元的作用
为什么要用到逆元呢?
在加、减、乘法中,都有如下等式:
( a + b ) % p = ( a % p + b % p ) % p (a+b)\%p=(a\%p+b\%p)\%p (a+b)%p=(a%p+b%p)%p
( a − b ) % p = ( a % p − b % p ) % p (a-b)\%p=(a\%p-b\%p)\%p (a−b)%p=(a%p−b%p)%p
( a × b ) % p = ( a % p × b % p ) % p (a\times b)\%p=(a\%p\times b\%p)\%p (a×b)%p=(a%p×b%p)%p
除法例外,但是有了逆元之后,就有以下等式
a b % p = ( a × x ) % p \frac{a}{b}\%p=(a\times x)\%p ba%p=(a×x)%p
其中 x x x 就称为 a a a模 b b b的逆元
费马小定理
可以简单的理解成:如果 p p p是一个质数,而整数 a a a不是 p p p的倍数,则有 a p − 1 % p = 1 a ^ {p-1}\%p=1 ap−1%p=1
显然,当 p p p为质数时,有 ( a × a p − 2 ) % p = 1 (a\times a ^ {p-2})\%p=1 (a×ap−2)%p=1,那么 a p − 2 a^{p-2} ap−2就是a的逆元。
这里我们可以用快速幂求得 a a a的逆元 x x x
代码如下:
ll quick_pow(ll a, ll b)
{
ll res = 1;
while (b)
{
if (b & 1)
res *= a;
b /= 2;
a = a * a % mod;
res %= mod;
}
return res % mod;
}
inline ll get_niyuan(ll a)
{
return quick_pow(a, mod - 2);
}