求逆元

求逆元


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


/*
扩展欧几里得法(求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;
    }
}



posted @ 2017-09-27 10:47  Bryce1010  阅读(97)  评论(0编辑  收藏  举报