求逆元

来源:互联网 发布:医生转行 知乎 编辑:程序博客网 时间:2024/05/17 23:15

求逆元


第一种方法:扩展欧几里得法


/*扩展欧几里得法(求ax+by=gcd)返回d=gcd(a,b);和对应等式ax+by=d中的x、y*/typedef long long ll;ll extendGcd(ll a,ll b,ll &x,ll &y){    if(a==0&&b==0)    {        return -1;    }    if(b==0)    {        x=1;        y=0;        return a;    }    ll d=extendGcd(b,a%b,y,x);    y-=a/b*x;    return d;}//求逆元ax=1(mod n)ll modReverse(ll a,ll n){    ll x,y;    ll d=extendGcd(a,n,x,y);    if(d==1)        return (x%n+n)%n;    else        return -1;//表示无逆元}



第二种方法:简洁写法

/*求逆元的简洁写法只能求a<m的情况,且a与m互质求ax=1(mod m)的x的值,即逆元(0<a<m)*/typedef long long ll;ll inv(ll a,ll m){    if(a==1)        return 1;    return inv(m%a,m)*(m-m/a)%m;}


第三种:欧拉函数求逆元(费马小定理)


逆元的几种求法(扩展欧几里得,费马小定理或欧拉定理,特例,打表等)


/*欧拉函数法mod为素数,而且a和m互质*///快速幂取模ll powM(ll a,ll b,ll m){    ll tmp=1;    if(b==0)return 1;    if(b==1)return a%m;    tmp=powM(a,a>>1,m);    tmp=tmp*tmp%m;        if(b&1)    {        tmp=tmp*a%m;    }    return tmp;}ll inv(ll a,ll m){    return powM(a,m-2,m);}

第四种:求阶乘逆元


typedef long long ll;const ll MOD = 1e9 + 7;     //  必须为质数才管用const ll MAXN = 1e5 + 3;ll fac[MAXN];       //  阶乘ll inv[MAXN];       //  阶乘的逆元ll QPow(ll x, ll n){    ll ret = 1;    ll tmp = x % MOD;    while (n)    {        if (n & 1)        {            ret = (ret * tmp) % MOD;        }        tmp = tmp * tmp % MOD;        n >>= 1;    }    return ret;}void init(){    fac[0] = 1;    for (int i = 1; i < MAXN; i++)    {        fac[i] = fac[i - 1] * i % MOD;    }    inv[MAXN - 1] = QPow(fac[MAXN - 1], MOD - 2);    for (int i = MAXN - 2; i >= 0; i--)    {        inv[i] = inv[i + 1] * (i + 1) % MOD;    }}



原创粉丝点击