深入浅出乘法逆元

蹲街弑〆低调 提交于 2020-11-16 01:56:17

深入浅出乘法逆元  1.模的运算律  2.定义  3.求解   3.1费马小定理   3.2扩展欧几里得算法   3.3线性求解

<h2 id='1'> 深入浅出乘法逆元 </h2> <h4 id='1.1'> 模的运算律 </h4> 先来一波模运算律表:

运算律 内容
交换律 $(a+b)%p=(b+a)%p$<br>$(a\times b)%p=(b\times a)%p$
结合律 $((a+b)%p+c)%p=(a+(b+c)%p)%p$<br>$((a\times b)%p\times c)%p=(a\times (b\times c)%p)%p$
分配率 $((a+b)%p\times c)%p=((a\times c)%p+(b\times c)%p)%p$<br>$(a\times b)%p=(a%p\times b%p)%p$<br>$(a+b)%p=(a%p+b%p)%p$<br>$(a-b)%p=(a%p-b%p)%p$

<h4 id='1.2'> 定义 </h4> 有的时候我们需要对一个数取模,这很简单。但是在取模的过程中出现了除数,那么取模就没这么简单了: $$\frac{7}{2}\%4=3\%4=3$$注意:$\frac{7\%4}{2}=\frac{3}{2}=1$是<font color=red>错误的</font> 但万一是$\frac{7^{10000}}{2}\%4$计算机可无法先计算$\frac{7^{10000}}{2}$再$\pmod4$,因为数字太大了。 这个时候我们就需要用到乘法逆元了,事实上:$\frac{7^{10000}}{2}=(7*3)^{10000}$。我们运用模的运算律可以通过边乘边取模即可得到答案,其中3是7在$\pmod 4$意义下的逆元。 关于逆元的严格定义如下: >$若整数b,m互质,并且b\mid a,则存在整数x,使得a/b\equiv a*x\pmod m,则称x为b的模m乘法逆元,记为b^{-1}\pmod m$

<h4 id='1.3'> 求解 </h4> <h5 id='1.3.1'> 3.1费马小定理 </h5>[^1] 因为$a/b\equiv a*b^{-1}\equiv a/b*b*b^{-1}\pmod m$,所以$b*b^{-1}\equiv 1\pmod m$[^2] 如果m是质数(此时我们用符号$p$代替$m$)并且$b<p$,根据费马小定理$b^{p-1}\equiv 1\pmod p$,即$b*b^{p-2}\equiv1\pmod p$。因此,当模数$p$为质数时,$b^{p-2}$为$b$的乘法逆元。 到最后我们可以用快速幂来迅速求出$b^{p-2}$。代码如下:

int ksm(int a,int b,int p) {
	int ans=1;
	for(; b; b>>=1,a=a*a%p)if(b&1)ans=ans*a%p;
	return ans;
}

时间复杂度是$O(\log n)$

<h5 id='1.3.2'> 3.2扩展欧几里得算法 </h5> 扩展欧几里得算法的具体内容参考我写的:[浅析扩展欧几里得算法(exgcd)](http://www.cnblogs.com/kcfzyhq/p/8485063.html) 根据逆元的定义我们要求的是$a*x\equiv1\pmod m$关于x的同余方程,其中x为a在$\pmod m$意义下的逆元 事实上$$ax=my+1······①$$也就是$ax\div m=y······1$ 变形①式得:$$ax-my=1$$ 既然$a,b$都已知,就不难求出$x和y$了(但要注意$y$的系数$-b$必须是正整数,因为在计算机计算过程中如果模数是负的将导致结果出错)如果$-b$不是正整数,我们同时改变$a,b$的符号即可。扩展欧几里得算法代码如下: ```cpp int exgcd(int a,int b,int &x,int &y) { if(b) { int c=exgcd(a,b,y,x); y-=a/b*x; return c; } else { x=1; y=0; return a; } } ``` 时间复杂度是$O(\ln n)$ <h5 id='1.3.3'> 3.3线性求解 </h5> 当我们需要求解大量的逆元的时候,前两种的方法时间复杂度都要乘以$n$,时间复杂度都不是很理想。所以我们就用$O(n)$的时间来快速求解。具体做法如下:假设我们要求x的逆元,那么:$$m=k*x+r$$$$k*x+r\equiv0\pmod m$$同乘以$x^{-1}*r^{-1}$得:$$k*r^{-1}+x^{-1}\equiv0\pmod m······①$$将②式变形得:$$x^{-1}\equiv-k*r^{-1}\pmod m$$ 所以我们得到:$$x^{-1}=-\lfloor m/x\rfloor*(m\%x)^{-1}$$ 那么只要建一个数组inv,初始值inv[1]=1。所以代码如下:

	for(int i=2; i<=n; i++)
		inv[i]=-(p/i)*inv[p%i];

[^2]: $b^{-1}\equiv b^{-1}\pmod m$其中前一个是$\div b$,后一个是$a$的逆元$b$;根据模的运算律$(a/bbb^{-1})%m=((a/b)%m*((bb^{-1})%m)%m$,显然$(bb^{-1})%m=1$

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!