先来看几个同余式:
1.(a+b)%p=(a%p+b%p)%p;
2. (a-b)%p=(a%p-b%p)%p;
3. (ab)%p=(a%pb%p)%p;
然而当变成除法的时候同余式便不对了即:(a/b)%p不等于(a%p/b%p)%p想要解决这个问题我们就可以把除法变成乘法,即变成(a%p*(1/b)%p)%p这样就正确了,那么这里%p情况下的1/b就是b的逆元。
理解了什么是逆元,那么就要解决怎么求逆元。
根据定义可得:(b*(b的逆元))%p==1,我们很快就可以联想到另一个式子费马小定理:当a与p互质时,a^(p-1)==1(%p),那么
a^(p-2)==1/a(%p),那么一个数a在模p情况下的逆元其实就是pow(a,p-2)%p.
代码:
#include <bits/stdc++.h>//普通乘法逆元(1/a=a^(p-2)%p)
using namespace std;
#define int long long
int n,m;
int ksm(int a,int k){
int ans=1,cnt=a;
while(k){
if(k&1){
ans=ans*cnt%m;
}
cnt=cnt*cnt%m;
k>>=1;
}
return ans%m;
}
signed main(){
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
int t=ksm(i,m-2);
cout<<t<<endl;
}
return 0;
}
还有一种一连串数字模p求逆元的情况存在递推式。
乘法逆元模板题
具体代码:
#include <bits/stdc++.h>//线性递推逆元
using namespace std;
#define ll long long
int n,p; int inv[3000005];//存对应下标逆元
signed main(){
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
scanf("%d %d",&n,&p); inv[1]=1; printf("%d\n",1);
for(int i=2;i<=n;i++){
inv[i]=(ll)(p-p/i)*inv[p%i]%p;
printf("%d\n",inv[i]);
}
return 0;
}