首页 > 其他 > 详细

乘法逆元模板

时间:2015-12-09 23:14:01      阅读:286      评论: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
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!