乘法逆元
乘法逆元
若整数\(b,p\)互质,并且\(b|a\),则存在一个整数\(x\)使得\(a/b≡a*x(mod p)\) ,则称\(x\)为\(b\) mod \(p\)的乘法逆元
记为\(b-1\)(mod \(p\))
我们先来看看有什么用
当输出结果很大时,要模一个mod再输出
\((a+b)\%mod=a\%mod+b\%mod\)
\((a-b)\%mod=a\%mod-b\%mod\)
\((a*b)\%mod=a\%mod*b\%mod\)
\((a/b)\%mod\)
乘法逆元派上用场了,设\(b\)模\(p\)的乘法逆元为\(inv\)
\((a/b)\%p=(a*inv)\%p=a\%p*inv\%p\)
为什么呢? 因为\(b*inv≡1(mod p)\)
\(a/b*b*inv=a*inv≡ a/b(mod p)\)
举个例子 要求(110/10)%7
\(11x≡1 (mod 7) x=9\)
\((110/10)\%7=(110\%7)*(9\%7)=5*2\%7=3\)
接下来是三种代码实现
1扩展欧几里得(exgcd) O(nlogn)
\(ax!≡1\)(mod \(p\)) 设\(ax=yp+1,b=-p\) 则\(ax+by=1\)
void exgcd(int a,int b)
{
if(b==0) g=a,x=1,y=0;
else{
exgcd(b,a%b);
int x1=y,y1=x-a/b*y;
x=x1,y=y1;
printf("%d*(%d)+%d*(%d)=%d\n",a,x,b,y,g);
}
}
inv[a]=(x+p)%p;
2费马小定理O(nlogn)
复杂度 欧拉函数\(O(n)\),快速幂\(O(logn)\)
假如\(p\)是质数,且\(gcd(a,p)=1\),那么 \(a^{p-1}≡1\)(mod \(p\))
由费马小定理 \(a^{p-1} ≡1\)$ , 变形得$$aa^{p-2}≡1\((mod p),答案已经很明显了:若\)a,p\(互质,因为且\)aa^{p-2}≡1$$(mod p)且a*x≡1(mod p)\(,则\)x=a^{p-2}$,用快速幂可快速求之.
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=3e6+5;
inline int read() {
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x;
}
typedef long long LL;
int n,p;
inline LL qpow(LL a,LL b) {
LL ans=1;
while(b) {
if(b&1) ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
int main() {
n=read();p=read();
for(int i=1;i<=n;+i++)
printf("%d\n",qpow(i,p-2));
return 0;
}
3欧拉定理O(nlogn)
定理内容:如果\(a,p\)互质,那么\(a^φ(p) ≡ 1\),当 p 为质数时,\(φ(p)=p-1\)。
同理,结合同余方程,得 \(x=a^{p-2}\)(mod p),用快速幂可快速求之即可
代码同上
4线性递推 O(n)
#include<bits/stdc++.h>
using namespace std;
#define N 3000010
typedef long long ll;
int n,p;
ll inv[N];
int main(){
scanf("%d%d",&n,&p);
puts("1");
inv[1]=1;
for(int i=2;i<=n;i++) {
inv[i]=(ll)p-(p/i)*inv[p%i]%p;
printf("%lld\n",inv[i]);
}
return 0;
}
lg T118233 一本通(蓝)P400