什么叫乘法逆元?
这里,我们称 x 是 a 关于 m 的乘法逆元
这怎么求?可以等价于这样的表达式: a*x + m*y = 1
怎么求逆元?
1,扩展欧几里德算法求逆元
int ex_gcd(int a,int b,int &x,int &y){ if(!b){ x=1,y=0; return a; } int ans=ex_gcd(b,a%b,y,x); y-=a/b*x; return ans; } int inv(int a,int mod){ int x,y; int ans=ex_gcd(a,mod,x,y); if(ans==1) return (x%n+n)%n; return -1; }
2,如果为素数,那么还可以根据费马小定理得到逆元为。
推导过程如下
根据上式,若求ans=(a/b) mod m,可转换成求a*inv[b] mod m (inv[b]为b的逆元:b^(m-2) ,用快速幂求)
3,
现在来看一个逆元最常见问题,求如下表达式的值(已知)
当然这个经典的问题有很多方法,最常见的就是扩展欧几里得,如果是素数,还可以用费马小定理。
但是你会发现费马小定理和扩展欧几里得算法求逆元是有局限性的,它们都会要求与互素。实际上我们还有一
种通用的求逆元方法,适合所有情况。公式如下
现在我们来证明它,已知,证明步骤如下
4,
其实有些题需要用到模的所有逆元,这里为奇质数。那么如果用快速幂求时间复杂度为,
如果对于一个1000000级别的素数,这样做的时间复杂度是很高了。实际上有的算法,有一个递推式如下
它的推导过程如下,设,那么
对上式两边同时除,进一步得到
再把和替换掉,最终得到
初始化,这样就可以通过递推法求出模奇素数的所有逆元了。
另外模的所有逆元值对应中所有的数,比如,那么对应的逆元是。