求逆元

来源:互联网 发布:安兔兔网络连接失败 编辑:程序博客网 时间:2024/06/07 15:56

ACM模版

扩展欧几里得法

参考:《GCD》

/* *  扩展欧几里得法(求ax + by = gcd) *///  返回d = gcd(a, b);和对应于等式ax + by = d中的x、ylong long extendGcd(long long a, long long b, long long &x, long long &y){    if (a == 0 && b == 0)    {        return -1;  //  无最大公约数    }    if (b == 0)    {        x = 1;        y = 0;        return a;    }    long long d = extendGcd(b, a % b, y, x);    y -= a / b * x;    return d;}//  求逆元 ax = 1(mod n)long long modReverse(long long a, long long n){    long long x, y;    long long 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) */long long inv(long long a, long long m){    if (a == 1)    {        return 1;    }    return inv(m % a, m) * (m - m / a) % m;}

欧拉函数法

/* *  欧拉函数法 *  mod为素数,而且a和m互质 *///  快速幂取模long long powM(long long a, long long b, long long m){    long long 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;}long long inv(long long a, long long 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;    }}
                                PS:2016.12.14添加

0 0