定义
若
a×x≡1(modb)
且
a,b
互质,我们就称
x
为
下面给出逆元的几种求法。
扩展欧几里得求逆元
扩展欧几里得在这里。
因为
a×x≡1(modb)
,所以
a×x=b×y+1
,等价于
a×x+b×y=1
,这就是一个可以用欧几里得求解的线性方程了。
在这里已经介绍出了如何利用原结论求出这个方程的解。
下面给代码:
void exgcd(int a,int b,int c,int &x,int &y)
{
int ret,tmp;
if(a==0)
{
x=0;
y=c/b;
return;
}
int tx,ty;
exgcd(b%a,a,c,tx,ty);
x=ty-(b/a)*tx;
y=tx;
return;
}
费马小定理求逆元
设
p
是一个素数,
所以我们发现有: a×ap−2≡1(modp) ,所以当 p 是素数时候,
注意点:费马小定理在 p 是素数而且
变式:对任意整数 a ,有
在 a,p 互质的时候,两个结论是等价的;如果 a,p 不互质,那么只有后者成立。
证明
首先,
p−1
个整数
a,2a,3a,4a…,(p−1)a
中没有一个是
p
的倍数。(因为p是质数而且ap还互质)。
其次
于是这些数再加上
所以:
a×2a×3a×…×(p−1)a≡1×2×3×…×(p−1)(modp)
化简:
ap−1×(p−1)!≡(p−1)!(modp)
因为
p
是质数,所以
这个情况只有在
p
是素数而且
代码
费马小定理使用的方法就很简单了,快速幂!
线性递推算法
声明:下面所有的运算都是在
modp
意义下进行的。
首先1的逆元是1。接下来我们表示逆元使用这个方法
a−1
。
我们设
p=k×i+r(r<i,1<i<p)。
如果把这个式子放在
modp
意义下,则会有
k×i+r≡0(modp)
两边同乘以
(i−1×r−1)
就会有:
所以我们就得到了代码:
A[i]=-(p/i)\times A[p % i];
这个方法适用于求多个整数的逆元。
对数级算法求逆元
我们由线性算法可以得到,我们可以不停地使用上述的公式递归,显然可以证明
pmodi<p/2
。
所以我们发现每次的问题规模都缩小了一半,所以时间复杂度
O(log2p)
。
代码:
int ny(int i)
{
return i==1 ? 1 : (-ny(p%i)*p/i)%p;
}