求逆元
\quad 逆元和我们平时所说的倒数是有一定的区别的,我们平时所说的倒数是指: a ∗ 1 a = 1 a*\frac{1}{a}= 1 a∗a1=1,那么逆元和倒数之间的区别就是:假设 x x x是 a a a的逆元,那么 a ∗ x = 1 % p a * x = 1\%p a∗x=1%p,它们拥有相同的余数,那么 a , x a,x a,x互为模 p p p的逆元。也就是说,有两个数的乘积,如果模 p p p后等于 1 1 1,则它们互为 p p p的逆元)。也就是只多了一个取余的操作,这个取余的操作,就会保证 a a a的逆元不一定只是 a a a的倒数。那么我们的逆元有什么作用呢?
\quad 并且取余还不满足下面式子:
\quad \quad \quad \quad \quad \quad a b % p = a % p b % p % p \frac{a}{b}\%p = \frac{a\%p}{b\%p} \% p ba%p=b%pa%p%p ,
那么我们如果遇到 b b b过大必须在中间过程进行取余的操作,那么我们会发现在乘法中满足: ( a ∗ b ) % p = ( a % p ∗ b % p ) % p (a*b) \% p = (a\%p * b\%p) \%p (a∗b)%p=(a%p∗b%p)%p,那么我们只要将上面式子转换为下面乘法的式子就可以了
我们用 i n v ( b ) inv(b) inv(b)来表示b的逆元,那么他一定满足:
\quad
\quad
b
∗
i
n
v
(
b
)
=
1
%
p
ˉ
→
b
=
1
i
n
v
(
b
)
\bar{b*inv(b) = 1\%p}\to{b = \frac{1}{inv(b)}}
b∗inv(b)=1%pˉ→b=inv(b)1,
那么我们代入上面的除法的式子:
\quad \quad a b % p = ( a ∗ i n v ( b ) ) % p = ( a % p ∗ i n v ( b ) % p ) % p \frac{a}{b}\%p = (a * inv(b)) \%p = (a\%p * inv(b)\%p) \% p ba%p=(a∗inv(b))%p=(a%p∗inv(b)%p)%p
\quad \quad \qquad 即: a b % p = ( a % p ∗ i n v ( b ) % p ) % p \frac{a}{b}\%p= (a\%p * inv(b)\%p) \% p ba%p=(a%p∗inv(b)%p)%p
\quad 这样我们就可以根据逆元来将除法取余的式子转换为乘法取余的式子
逆元的计算
我们这里先介绍第一种计算逆元的方式,利用费马小定理计算逆元。
费马定理可以参考这篇博客:点击这里
费马小定理:如果
p
p
p是质数(素数),并且
g
c
d
(
a
,
p
)
=
=
1
gcd(a,p) == 1
gcd(a,p)==1, 那么就会满足下面的式子
a
p
−
1
≡
1
%
p
a^{p−1} ≡1\%p
ap−1≡1%p ,(当然了,既然
p
p
p已经是素数,那么如果
a
<
p
a < p
a<p那么就一定会满足这个式子)。既然这样我们要得到
a
a
a我们就可以利用上面的式子来计算
i
n
v
(
a
)
:
inv(a) :
inv(a):
\quad \quad \quad a p − 1 = 1 % p a^{p−1} =1\%p ap−1=1%p
\quad
\quad
\quad
a
∗
a
p
−
2
=
1
%
p
a*a^{p−2}=1\%p
a∗ap−2=1%p
\quad
a
a
a的逆元就是
(
a
p
−
2
)
%
p
(a^{p-2})\%p
(ap−2)%p
可得:
\quad \quad \quad \quad \quad \quad i n v ( a ) = ( a p − 2 ) % p inv(a)=(a^{p-2})\%p inv(a)=(ap−2)%p
这样我们就得到了我们需要的逆元:
Code:
ll qpow(int m, int k, int mod)
{
ll res=1, t=m;
while (k)
{
if(k&1)
res = res * t % mod;
t = t * t % mod;
k >>= 1;
}
return res;
}
// 快速幂求逆元
int Fermat(int a, int p) //费马求a关于b的逆元
{
return qpow(a,p-2,p);
}
扩展欧几里得求逆元:
扩展欧几里得可以参考这篇博客:点击这里
a
∗
x
+
b
∗
p
=
1
a*x+b*p=1
a∗x+b∗p=1两边对p取模
可得:
a
∗
x
=
1
%
p
a*x=1\%p
a∗x=1%p
\quad
x
x
x 就是我们要求得逆元。
在
g
c
d
(
a
,
p
)
gcd(a,p)
gcd(a,p)不为
1
1
1说明逆元不存在
由扩展欧几里得可得
Code:
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int g=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return g;
}
int mod_reverse(int a,int p)//a*x=1(mod p) 求a的逆元x
{
int d,x,y;
d=exgcd(a,p,x,y);
if(d==1)
return (x%p+p)%p;
else
return -1;
}