(模板)求乘法逆元

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.求连续阶乘的乘法逆元
这里写图片描述
注意求出来的是阶乘的逆元;

猜你喜欢

转载自blog.csdn.net/humveea6/article/details/79876591