逆元 学习笔记
定义&&作用
如果 \(ax\equiv 1 \pmod b\) 并且 \(\gcd(a,b)=1\) 那么我们称 \(x\) 为 \(a \bmod b\) 的逆元,记做 \(a^{-1}\) 或者是 \(\frac{1}{a}\) 。
这样我们就可以求出任意实数 \(\frac{a}{b}\) 在模 \(p\) 意义下的值了(通常 \(p\) 是质数)。
求逆元
这里求的是在模 \(p\) 意义下的 \(a^{-1}\) 的值。
快速幂
不难得出 \(x=a^{p-2}\bmod p\) 用快速幂做即可,复杂度 \(O\left(\log_2p\right)\)
证明如下:
法一:费马小定理
因为 \(p\) 是素数并且 \(\gcd(a,p)=1\)
所以 \(a^{p-1}\equiv 1\pmod p\)
所以 \(a\times a^{p-2} \equiv 1 \pmod p\)
所以 \(x=a^{p-2}\bmod p.\)
法二:欧拉定理
因为 \(\gcd(a,p)=1\)
所以 \(a^{\varphi(p)}\equiv 1 \pmod p\)
因为 \(p\) 是素数,所以 \(\varphi(p)=p-1\)
所以 \(a^{p-1}\equiv 1\pmod p\)
所以 \(a\times a^{p-2} \equiv 1 \pmod p\)
所以 \(x=a^{p-2}\bmod p.\)
int pow(int x,int y){
ll res=1,tmp=x;
while(y>0){
if(y&1) res=res*tmp%p;
tmp=tmp*tmp%p;
y>>=1;
}
return res%p;
}
int js(int a,int p){// a^-1%p
return pow(a,p-2);
}
exgcd
根据定义 \(ax\equiv 1 \pmod p\) 并且 \(\gcd(a,p)=1\)
我们发现满足 \(ax+py=gcd(a,p)=1\)
exgcd即可,不会的点这里
void exgcd(int a,int b,int &x,int &y){
if(!b){ x=1; y=0; return; }
exgcd(b,a%b,x,y);
int t=x;
x=y; y=t-a/b*y;
return;
}
int js(int a,int p){//a^-1%p
int x,y;
exgcd(a,p,x,y);
return (x%p+p)%p;
}
线性求逆元
题目传送门
题目大意:给定 \(n,p\) 求 \(1\sim n\) 中所有整数在模 \(p\) 意义下的乘法逆元。
显然直接一个一个求是不可能的,这里介绍如何线性求(算法复杂度 \(O\left(n\right)\) )。
首先 \(1^{-1}\equiv 1 \pmod p\)
我们设 \(p=aq+r,0\leq r<a\)
那么 \(q=\lfloor \frac{p}{a} \rfloor,r= p\bmod a\) 并且 \(aq+r \equiv 0 \pmod p\)
移项,得 \(r\equiv -aq \pmod p\)
等式两边同时乘上 \(r^{-1}a^{-1}\) , 得到 \(a^{-1} \equiv q\times r^{-1} \pmod p\)
所以 \(a^{-1} \equiv -\lfloor \frac{p}{a} \rfloor \times ({p \bmod a}) \pmod p\)
开个数组 \(inv_i\) 代表 \(i^{-1}\) 即可。
int inv[maxn];//inv[i]->i^-1(mod p)
void solve(){
inv[0]=0; inv[1]=1;
for(int i=2;i<=n;i++)//long long
inv[i]=(ll)(p-p/i)*(ll)inv[p%i]%p;
for(int i=1;i<=n;i++)
printf("%d\n",inv[i]);
}
阶乘逆元线性求
显然我们发现 \(\frac{1}{a!} \equiv \frac{a+1}{\left(a+1\right)!} \pmod p\)
所以 \(a!^{-1} \equiv \left(a+1\right)!^{-1}\times \left(i+1\right) \pmod p\)
我们只要求出 \(n!^{-1}\) 就可以求出 \(1!^{-1},2!^{-1},\dots,\left( n-1\right)!^{-1}\) 了。
算法复杂度 \(O\left(n\right)\)
END.