乘法逆元的研究

介绍

模世界真是奇妙无穷
我们已经很轻松地学会了乘法,加法,减法的取模运算规则。
但是我们却对除法取模毫无办法。
直接模?显然不行,例如:

\[30/10\%3=2 \]

\[(30\%3)/(10\%3)=0 \]

很明显结果是不一样的。
我们这里理由倒数的思想,定义出了乘法逆元。

定义

对于一个数a,若存在\(a\times b\equiv 1(mod\ p)\)
那么我们将\(b\)记为\(a\)关于模数\(p\)的乘法逆元

那么我们怎么求得这个值呢?

算法

拓展欧几里得算法

拓展欧几里得可以解出\(ax+by=gcd(a,b)\)这个不定方程的特解。
对于一个形如\(ax\equiv b \pmod p\)的式子,我们可以把原式写成\(ax+py=b\)的形式,这是一个二元一次不定方程。
根据裴蜀定理,如果\((a,p)\mid b\),那么这个方程的解为无数个,反之无解。

那么如何解这个方程呢?
我们可以通过拓展欧几里德算法在递归求解\((a,b)\)顺便求解(以下简称拓欧)。
\((a,b)=d\)
显然我们在\(b=0,a\neq0\)时可以得到一组特解\(x_0=1,y_0=0\),满足\(bx_0+(b\%a)y_0=d\)
在回溯的时候,我们就有了\(b x_0+(b \% a)y_0=d\)的解,如何利用这个解求出\(ax+by=d\)的解呢?
对于一个取模,我们有\(a\%b=a-b\times \lfloor \frac{a}{b} \rfloor\)
我们对原式进行转化,可以转化为\(b x_0+(a-b\times \lfloor \frac{a}{b} \rfloor)y_0=d\)
原式提取出\(a,b\)我们可以化简为\(y_0a+(x_0-\lfloor \frac{a}{b} \rfloor y_0)b=d\)
这样我们就可以进行递归求解了。
当然求出来的仍然是一组特解,但是我们很容易通过等式的性质把它转化为通解:\(atx+bty=t\gcd(a,b)\)
我们通过算数变换就能把它调整到任意\([p,p+\gcd(a,b)]\)范围内。

int exgcd(int a,int b,int &x,int &y){
	if(b==0){
    	x=1;y=0;
        return a;
    }
    int d=exgcd(b,a%b,x,y),t=x;
    x=y;y=t-(a/b)*y;
}

我们发现如果在同余方程\(x^{-1}x\equiv 1\pmod p\)中,\(x^{-1}\)就是\(x\)\(\mod p\)意义下的乘法逆元。
那么我们可以通过求解这个同余方程解出这个\(x^{-1}\)

费马小定理

利用费马小定理,我们有\(a^{p-1}\equiv 1(mod\ p)\)
那么a的乘法逆元就是\(a^{p-2}\)
注意这里p必须是质数,并且a,p互质。

欧拉定理以及数论阶

当p不保证为质数的时候,我们可以用欧拉定理以及数论阶求出a最小的逆元。
代码留坑

线性求逆元

上面都是log的做法,但是当我们要求大量逆元时(比如求组合数)。
log的单次询问做法就不怎么管用了。
我们需要一种更加高效的算法,支持\(O(n)\)预处理,\(O(1)\)查询。

假设我们已经拥有了\(1~i-1\)关于模数p的(以下简称逆元)
那么我们设

\[p=i*k+r \]

那么在模p意义下

\[i*k+r\equiv 0(mod\ p) \]

我们给两边同乘\(i^{-1}*r^{-1}\)

\[k*r^{-1}+i^{-1}\equiv 0(mod\ p) \]

移项得

\[i^{-1}\equiv -k*r^{-1}(mod\ p) \]

由于\(r=p\%i\)\(k=p/i\)我们得到

\[i^{-1}\equiv -(p/i)*(p%\i)^{-1} \]

这两个我们都已经得到了
我们就很轻松递推出\(i\)的逆元了。
注意这里 $ -(p/i)*(p%\i)^{-1}$为一个负数,我们在计算的时候要把它转化为正数。

int init(int n){
    inv[0]=inv[1]=1;
    for(int i=2;i<=n;i++)inv[i]=(p-p/i)*inv[p%i]%p;
}
posted @ 2018-10-31 19:30  _onglu  阅读(282)  评论(0编辑  收藏  举报