逆元
逆元,类似于倒数,
如果
a
x
≡
1
(
m
o
d
p
)
ax≡1 (mod p)
ax≡1(modp),且
g
c
d
(
a
,
p
)
=
1
gcd(a,p)=1
gcd(a,p)=1(a与p互质),则称a关于模p的乘法逆元为x。
注意:只有a和p互质的时候,a才有关于p的逆元,所以当有多个p和a互质时,所求的a关于p的逆元也是不同的。
a ∗ x ≡ 1 ( m o d p ) a*x ≡ 1 (mod \ p) a∗x≡1(mod p)
其中
x
x
x 叫做
a
a
a的关于
p
p
p的逆元,记为:
i
n
v
(
a
)
=
x
inv(a) = x
inv(a)=x
所以
a
∗
i
n
v
(
a
)
≡
1
(
m
o
d
p
)
a * inv(a) ≡ 1 (mod p)
a∗inv(a)≡1(modp)
例如:
若a*x = 1那么x是a的倒数,x = 1/a
但是a如果不是1,那么x就是小数
那数论中,这个mod出来这里不能有小数,所以现在问题变了
我们可以这么写:
a
/
b
=
a
/
b
∗
b
∗
T
a/b=a/b*b*T
a/b=a/b∗b∗T (T为b的逆元,这里省略了mod操作,太懒了不想写 )
1
=
b
∗
T
1=b*T
1=b∗T
但是如何去求逆元呢?我们引入一个定理:(邦邦卡邦~~~)
费马小定理(Fermat’s little theorem)是数论中的一个重要定理,在1636年提出,其内容为:
假如p是质数,且 g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1,那么 a ( p − 1 ) ≡ 1 ( m o d p ) a^{(p-1)}≡1(mod\ p) a(p−1)≡1(mod p),
即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。
接着继续:
a ( p − 1 ) = 1 ( m o d p ) a^{(p-1)}=1(mod\ p) a(p−1)=1(mod p)
a ∗ a ( p − 2 ) = 1 ( m o d p ) a*a^{(p-2)}=1(mod\ p) a∗a(p−2)=1(mod p)
哎,是不是很像上面那个式子
我们把它拿过来看看:
b ∗ T = 1 b*T=1 b∗T=1
哎,这么一对应
我们发现
b 的逆元即为 b ( p − 2 ) b的逆元即为b^{(p-2)} b的逆元即为b(p−2)
线性求逆元
设 p = k ∗ i + j p=k*i+j p=k∗i+j
k ∗ i + j = 0 ( m o d p ) k*i+j=0\ (mod\ p) k∗i+j=0 (mod p)
k ∗ i ∗ ( i − 1 ∗ j − 1 ) + r ∗ ( i − 1 ∗ j − 1 ) = 0 ( m o d p ) k*i*(i^{-1}*j^{-1})+r*(i^{-1}*j^{-1})=0\ (mod\ p) k∗i∗(i−1∗j−1)+r∗(i−1∗j−1)=0 (mod p)
k ∗ j − 1 ∗ i − 1 = 0 ( m o d p ) k*j^{-1}*i^{-1}=0\ (mod\ p) k∗j−1∗i−1=0 (mod p)
i − 1 = − k ∗ j − 1 ( m o d p ) i^{-1}=-k*j^{-1}\ (mod\ p) i−1=−k∗j−1 (mod p)
i − 1 = − ⌊ p / i ⌋ ∗ k ∗ j − 1 ( m o d p ) i^{-1}=-\lfloor p/i \rfloor *k*j^{-1}\ (mod\ p) i−1=−⌊p/i⌋∗k∗j−1 (mod p)
再代入 j = p m o d i j=p\ mod\ i j=p mod i,得
i − 1 = − ⌊ p / i ⌋ ∗ ( p m o d i ) − 1 ( m o d p ) i^{-1}=-\lfloor p/i \rfloor *(p\ mod\ i)^{-1}\ (mod\ p) i−1=−⌊p/i⌋∗(p mod i)−1 (mod p)
我们可以发现,这个 ( p m o d i ) (p\ mod\ i) (p mod i)是小于i的,也就是我们求过,所以我们可以用递推求出
也就是以下伪代码:
i n v [ i ] = − ⌊ p / i ⌋ ∗ i n v [ p m o d i ] inv[i]=-\lfloor p/i \rfloor *inv[p\ mod\ i] inv[i]=−⌊p/i⌋∗inv[p mod i]
代码如下:
inv[1] = 1;
for (int i = 2; i <= n; ++i) {
inv[i] = (long long)(p - p / i) * inv[p % i] % p;
}
来看个例题吧
AC代码: