码迷,mamicode.com
首页 > 其他好文 > 详细

乘法逆元模板

时间:2015-12-09 23:16:15      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:

1.扩展欧几里得求逆元

typedef long long ll;

//ax + by = gcd(a,b)
//传入固定值a,b.放回 d=gcd(a,b), x , y
void extendgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if(b==0){d=a;x=1;y=0;return;}
    extendgcd(b,a%b,d,y,x);
    y-=x*(a/b);
}

//Ax=1(mod M),gcd(A,M)==1
//输入:10^18>=A,M>=1
//输出:返回x的范围是[1,M-1]
ll GetNi(ll A,ll M)
{
    ll rex=0,rey=0;
    ll td=0;
    extendgcd(A,M,td,rex,rey);
    return (rex%M+M)%M;
}

2.根据欧拉定理求逆元,当mod素数时可以速度较快。

//a^b%mod 快速幂
long long Quk_Mul(long long a,long long b,long long mod)
{
    long long qsum=1;
    while(b)
    {
        if(b&1) qsum=(qsum*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return qsum;
}

//欧拉函数:复杂度O(n^(0.5)),返回[1,n-1]中所有和n互素的数的个数和
ll phi(ll x)
{
    ll sum=x;
    for(ll i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            sum=sum-sum/i;
            while(x%i==0) x/=i;
        }
    }
    if(x!=1) sum=sum-sum/x;
    return sum;
}

//Ax=1(mod M),gcd(A,M)==1
//输入:10^18>=A,M>=1
//输出:返回x的范围是[1,M-1]
//复杂度:如果M是素数,则直接用M-2代替phi(M)-1 复杂度为O(logM)
//       如果M不是素数,则复杂度为O( M^(0.5) ) 好慢。
ll GetNi(ll A,ll M)
{
    //return Quk_Mul(A, phi(M)-1, M);
    return Quk_Mul(A, M-2, M);
}

3.对于a/b (mod m),不要求b和m互质。前提当然b能整除a

(a/b) % m等于a%(b*m)/b

只要是bm不需要高精度,这种方法是很好用的。

证明还是很好证的:

(a/b) mod m = a/b – k*m = (a – k*b*m)/b =(a%(b*m))/b;

 

乘法逆元模板

标签:

原文地址:http://www.cnblogs.com/chenhuan001/p/5034531.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!