若 a×x≡1(modb) 且 a,b 互质,我们就称 x 为 a 的逆元,记作 a−1 。
下面给出逆元的几种求法。
扩展欧几里得在这里。
因为 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 是和 p 互质的整数,则有:
首先, p−1 个整数 a,2a,3a,4a…,(p−1)a 中没有一个是 p 的倍数。(因为p是质数而且ap还互质)。
其次 a,2a,3a,4a…,(p−1)a 中没有两个模 p 同余的。
于是这些数再加上 ap 就构成了一个完系。所以 a,2a,3a,4a…,(p−1)a 在模 p 意义下是 1 p−1 的一种排列。
所以: a×2a×3a×…×(p−1)a≡1×2×3×…×(p−1)(modp)
化简:
ap−1×(p−1)!≡(p−1)!(modp)
因为 p 是质数,所以 (p−1)! 和 p 互质。约分后 ap−1≡(modp)
这个情况只有在 p 是素数而且 ap 互质才成立。一般地,若 p 是质数,则有:
ap≡a(modp)
费马小定理使用的方法就很简单了,快速幂!
声明:下面所有的运算都是在 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;
}