您的位置:首页 > 其它

扩展欧几里德

2016-08-20 16:59 134 查看
欧几里德



int gcd(int a,int b){
    if(b) while(b^=a^=b^=a%=b);
    return a;
}



扩展欧几里德

int ext_gcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    int ans=ext_gcd(b,a%b,y,x);
    y-=(a/b)*x;    //    x=y`   y=x`-[a/b]*y`
    return ans;
}

求得ax+by=gcd
若x+=k*(b/gcd)    y-=k*(a/gcd),等式一样成立

二进制gcd算法:
如果a和b都是偶数,则gcd(a,b)=2*gcd(a/2,b/2)
如果a是奇数,b是偶数,则gcd(a,b)=gcd(a,b/2)
如果a和b都是奇数,则gcd=(b,(a-b)/2)

例题: HDOJ 1576
题目:
     要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
做法:
     根据题目我们知道: n=A%9973=A-A/9973*9973。设A/B=x,则A=Bx。所以Bx-A/9973*9973=n。
     即Bx-9973y=n  ---① (y是多少不重要也不用管 ,用不上)

     题目所求的值就是x%9973的值

     利用扩展欧几里德算法可求出gcd(B,9973)=Bx1+9973y1=1 的x1,x=n*x1(等式两边乘于n就是①式了嘛)

     为什么可以这样做:①式有无数解,最原始的解就是x0 = x1* n/ gcd(B,9973)
     其他解可通过x=x0+t*9973, y=y0-t*B(t为整数)得来!!

     得到的x可能为负值,所以还需要x=(x%9973+9973)%9973。(x=abs(x)%9973是错的)
     怕不同编译器对余数的符号取法不一样出错,就用

if(x<0)   x=x+(-x/9973+1)*9973;
else      x=x%9973;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息