乘法逆元,是指数学领域群G中任意一个元素a,都在G中有唯一的逆元a‘,具有性质a×a’=a’×a=e,其中e为该群的单位元。(百度百科的解释,鬼才能看懂┑( ̄Д  ̄)┍)
我理解的乘法逆元是,若a*b≡1(mod p),则b是a的乘法逆元,a是b的乘法逆元,b也可以写成a-1
乘法逆元有什么用呢?
在取模运算中,有a*b%p=(a%p) * (b%p)
但是没有(a/b)%p=(a%p)/(b%p)
如果我们需要模一个很大的质数,而且恰好结果中还有除法,这时候我们就可以用它的逆元代替它,即,(a/b)%p=(a*b-1)%p=(a%p) *(b-1%p)(嫑问我为什么,因为我也不知道 ┑( ̄Д  ̄)┍)
在mod p运算中,a存在乘法逆元的充要条件是a与p互质
那么如何来求乘法逆元呢?
主要有三种方法
1、 扩展欧几里得。a*a-1≡1(mod p)可以转换成a*a-1 + py = 1,这就变成了扩展欧几里得了
long long extend_gcd(long long a, long long b, long long &x, long long &y) {
if (b) {
long long r = extend_gcd(b, a%b, y, x);
y -= x*(a/b);
return r;
} else {
x = 1;
y = 0;
return a;
}
}
2、费马小定理ap-1≡1(mod p)(p为素数),做一下变形得到a*ap-2≡1 (mod p),so,ap-2就是a的逆元了,ap-2直接用快速幂就能求了
3、网上看到的一个很厉害的o(n)的递推,求前n个逆元,不知道是怎么推出来的,但是可以简单地证明一下正确性(要求所mod p为素数)
首先,1的逆元是1,没什么疑问。
假设前i个数的逆元已经求出,那么
i-1 = (p%i)-1 * (p - [p/i]) % p。其中[]表示去尾取整。
(p%i)-1其实就是(p-[p/i]*i)-1,然后我们左右乘以i,
i*i-1 = (p-[p/i]i)-1 ((i-1)*p + p-[p/i]*i) % p,
其实就是i*i-1 = k-1 * ((i-1)*p + k) % p = 0 + 1 = 1,这样就证完了
int inv[MAXN];
inv[1] = 1;
for (int i = 2; i<MAXN; i++)
inv[i] = inv[MOD%i]*(MOD-MOD/i)%MOD;