乘法逆元
一、模运算的性质
- ( a + b ) % p = ( a % p + b % p) % p
- ( a + b ) % p =( ( a % p + b % p ) % p + p ) % p
注意:此处与上一个不一样,(9-7)%8=(9%8-7%8)%8=-6 ;不是我们要的值,这时要加上p
- ( a * b ) % p = ( ( a % p ) * ( b % p ) ) % p
二、除法的模运算
1、除法模运算
(a/b)%p=(a%p)/(b%p) ,如果我们保证可以整除,它是否成立呢?
取a=8,b=2,p=6; 左式=4,右式=1;也就是说 除法的模运算不一定成立。
2、解决除法模运算问题
能否将除法转化为乘法?找到 binv ,使得 ( a / b ) % p = = ( a ∗ b i n v ) % p (a/b)\%p==(a*b_{inv})\%p (a/b)%p==(a∗binv)%p ;若能,则称 b i n v b_{inv} binv为 b在模p意义下 的乘法逆元 ;
三、乘法逆元
1、定义
若在mod p意义下,对于一个整数a,有 ( a ∗ b ) (a*b)%p=1 (a∗b),那么这个整数b即为a的 乘法逆元,同时a也为b的乘法逆元。一个数有逆元的充分必要条件是gcd(a,p)=1,此时a才有对p的乘法逆元。
2、逆元是干什么的呢
首先对于除法取模不成立,即$ (a/b)%p!=(a%p)/(b%p)$。显然数学家们是不能忍受这种局面的,他们扔出了“逆元”来解决这个问题。因为取模运算对于乘法来说是成立的,逆元就是把除法取模运算转化为乘法取模运算。
(
a
/
b
)
%
p
=
m
(
1
)
(
a
×
x
)
%
p
=
m
(
2
)
(a/b)\%p=m (1)\\ (a \times x)\%p=m (2)
(a/b)%p=m(1)(a×x)%p=m(2)
(1)模运算对乘法成立,对①式左右两边同时乘以b,得到
a
%
p
=
(
m
×
b
)
%
p
a\%p=(m \times b)\%p
a%p=(m×b)%p
(2)如果a和b均小于模数p的话,上式得到:
a
=
m
×
b
a = m \times b
a=m×b
(3)等式两边同时乘以
x
x
x,联立②式得到:
(
a
×
x
)
%
p
=
m
%
p
=
(
m
×
b
×
x
)
%
p
(
b
×
x
)
%
p
=
1
(a \times x)\%p = m\%p=(m \times b \times x )\%p \\ (b \times x)\%p = 1
(a×x)%p=m%p=(m×b×x)%p(b×x)%p=1
即x就是b的逆元。(根据逆元的定义可知)总结:求取
(
a
/
b
)
(a/b)%p
(a/b)等同于求取
a
×
(
b
的逆元
)
a \times (b的逆元)%p
a×(b的逆元),因此,求模运算的除法问题就转化为求解一个数的逆元问题。
四、求解逆元
求解一个数的逆元有两种方法:费马定理和扩展欧几里得
1、费马小定理
因为在算法竞赛中模数p总是质数,所以可以使用费马小定理。
b
p
−
1
%
p
=
1
b^{p-1}\%p=1
bp−1%p=1
可以得到
b
×
b
p
−
2
%
=
1
b \times b^{p-2}\%=1
b×bp−2%=1,所以
b
p
−
2
b^{p-2}
bp−2是b在mod p条件下的逆元。
public class PowUtil {
public static Long quickPow(Long a,Long n,Long p){
//结果
Long res = 1L;
while (n != 0) {
//判断 n 的二进制的最后一位是否为0
if((n&1)!=0){
//当n的二进制最后一位为1时,乘以当前的权重
res = (res*a)%p;
}
//更新n,每次n向右移一位
n = n >> 1;
//更新每一位的权重
a = (a*a)%p;
}
return res;
}
}
public class InverseElement {
/**
* 利用b^(n-1)%p=1求解b的逆元
* @param a 质数
* @param p 模数
* @return a的逆元
*/
public static Long inverseElement(Long a,Long p){
//quickPow()是快速幂函数
return PowUtil.quickPow(a,p-2,p);
}
}
2、扩展欧几里得
(1)扩展欧几里得算法:求ax+by=gcd(a,b)的一组x,y
(2)求a在模p意义下的乘法逆元:
(
a
×
a
i
n
v
)
%
p
=
1
a
×
a
i
n
v
+
p
×
y
=
1
g
a
d
(
a
,
p
)
=
1
(a \times a_{inv})\%p=1 \\ a \times a_{inv} + p \times y = 1\\ gad(a,p)=1
(a×ainv)%p=1a×ainv+p×y=1gad(a,p)=1
代码展示
void exgcd(ll a, ll b, ll &x, ll &y) //拓展欧几里得算法
{
if(!b)
x = 1, y = 0;
else
{
exgcd(b, a % b, y, x);
y -= x * (a / b);
}
}
ll niyuan(ll a, ll b) //求a对b取模的逆元
{
ll x, y;
exgcd(a, b, x, y);
return (x + b) % b;
}