乘法逆元
乘法逆元在学扩展欧几里得时就接触过了,但是那时并不知道它有什么作用,今天又学,现做总结。
什么是逆元
\(a∗x\equiv1(mod\) \(b)\)(b和a互质),那么称x是a的乘法逆元。
应用
我们知道取余运算具有可加性,可减行,可乘性,但不具备可除性,即\((a/b)mod\) \(p\)不一定等于\((a\) \(mod\) \(p)/(b\) mod \(p)\)。这时逆元就有大作用了,当\(k\equiv b^{-1}(mod\) \(p)\)时,\((a*k)\equiv (a/b)(mod\) \(p)\),那么就可以用\((a\) \(mod\) \(p)*(k\) \(mod\) \(p)mod\) \(p=(a/b)mod\) \(p\)。
求法
- 费马小定理
\(a^{p-1}\equiv 1(mod\) \(p)\)(p是质数,gcd(a,p)=1)。
证明:建一个p的完全剩余系{1,2,3,……,p-1},因为\(gcd(a,p)=1\),所以{a,2a,3a,……,(p-1)a}也是p的完全剩余系,这里需要用反证法证明,设\(i,j\in\) {\(1,2,3……,p-1\)}且\(i\ne j\),\(a*i\equiv a*j(mod\) \(p)\),因为\(gcd(a,p)=1\),所以\(i\equiv j(mod\) \(p)\),即\(i=j\),与\(i\ne j\)矛盾,证得{a,2a,3a,……,(p-1)a}是p的完全剩余系。将这两个完全剩余系分别相乘,\((p-1)!\equiv (p-1)!*a^{p-1}(mod\) \(p)\),又因为p是质数,\(a^{p-1}\equiv 1(mod\) \(p)\)。
运用:因为\(gcd(a,p)=1\),所以\(a^{p-2}\equiv a^{-1}(mod\) \(p)\),\(a^{p-2}\)就是\(a^{-1}\)的逆元,快速幂求出\(a^{p-2}%p\)就可以了。
代码:
#include<iostream>
#define int long long
using namespace std;
int n,p;
int ksm(int a,int b){
if(b==0){
return 1;
}
int ans=ksm(a,b/2);
ans=(ans*ans)%p;
if(b%2==1){
ans=(ans*a)%p;
}
return ans;
}
signed main(){
cin>>n>>p;
cout<<ksm(n,p-2);
return 0;
}
- 扩展欧几里德算法
求逆元的思路:\(a*x\equiv 1(mod\) \(p)\)得\(a*x+p*y=1(<0\le x<p)\) - 线性求逆元
inv[i]表示i的逆元,即\(inv[i]\equiv i^{-1}(mod\) \(p)\)。
\(inv[1]=1\)
设\(p=q*k+r\),则\(q*k+r\equiv 0(mod\) \(p)\),因为p是质数,所以\(k*r^{-1}+q^{-1}\equiv 0(mod\) \(p)\),\(q^{-1}\equiv -k*r^{-1}(mod\) \(p)\),\(q^{-1}\equiv (p-k)*r^{-1}(mod\) \(p)\),递推式为\(inv[i]=(p-p/i)*inv[p\)%\(i]\)%\(p\)。
代码:
#include<iostream>
#define int long long
using namespace std;
int n,p;
int inv[3000010];
signed main(){
scanf("%d%d",&n,&p);
inv[1]=1;
printf("%d\n",inv[1]);
for(int i=2;i<=n;i++){
inv[i]=(p-p/i)*inv[p%i]%p;
printf("%d\n",inv[i]);
}
return 0;
}