常用的求逆元的方法有扩展欧几里得和费马小定理, 因为扩展欧几里得我还不会, 这里介绍一下费马小定理。
逆元的定义
有正整数 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 就称为 b b b模 p p p的逆元
费马小定理
可以简单的理解成:如果 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);
}