1.扩展欧几里得求乘法逆元
原理就是解线性同余方程;
void exgcd (ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1;
y = 0;
return ;
}
exgcd (b, a % b, x, y);
ll tmp = x;
x = y;
y = tmp - a / b * y;
}
ll x, y;
exgcd (a, b, x, y);//求a在模b意义下的乘法逆元
x = (x % p + p) % p;
printf ("%d\n", x);
2.利用费马小定理
前提是模数必须是质数;因为a^(p-1) mod p=1,所以a模p的乘法逆元就是a^(p-2)
运用快速幂
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <vector>
using namespace std;
typedef long long ll;
ll pow(ll x,ll n,ll mod)
{
ll ans=1;
x%=mod;
while(n){
if(n&1)
ans=ans*x%mod;
x=x*x%mod;
n>>=1;
}
return ans;
}
int main()
{
int n,p,i,j;
cin>>n>>p;
vector<int>ans;
for(i=1;i<=n;i++){
ll t=pow(i,p-2,p);
ans.push_back(t);
}
for(i=0;i<n;i++)cout<<ans[i]<<endl;
//cout<<ans[n-1]<<endl;
return 0;
}
3.递推求乘法逆元
用于求连续很多数的乘法逆元,时间复杂度基本上是线性
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
ll n,p,i,j;
cin>>n>>p;
ll inv[3000005];
inv[1]=1;
for(i=2;i<=n;i++)
inv[i]=(p-p/i)*inv[p%i]%p;//关键
for(i=1;i<=n;i++)
printf("%lld\n",inv[i]);
return 0;
}
4.求连续阶乘的乘法逆元
注意求出来的是阶乘的逆元;