• 扩展欧几里得算法


    欧几里得算法

    欧几里得算法就是大家以前学过的辗转相除法,可以用来计算两个数字的最大公约数((gcd)):

    (gcd(a,b)=gcd(b,a\%b))

    证明

    对于 (a,b (ale b)) 不妨设 (a=kb+r)

    (r=0) 则说明 (b|a) ,所以 (gcd(a,b)=b)

    (r e0) 则对于任意 (t|a)(t|b) ,都有 (t|kb) ,又因为 (a-kb=r) ,所以也有 (t|r) ,同理,对于任意 (t|r)(t|b) ,都有 (t|kb) ,又因为 (r+kb=a) ,所以也有 (a|r) ,所以 (a,b) 的所有公因数也就是 (b,r) 的所有公因数

    c++ code

    int gcd(int a,int b)
    {
        return b?gcd(b,a%b):a;
    }
    

    裴蜀定理(贝祖定理)

    (a,binmathbb{Z}) ,那么对于任意的 (x,yinmathbb{Z}) 都有 (ax+by=k*gcd(a,b)) ,其中 (kinmathbb{Z}) ,同时一定存在一组 (x,yinmathbb{Z}) 使得 (ax+by=gcd(a,b)) 成立

    换言之,当且仅当 (gcd(a,b)|m) 时关于 (x,y) 的方程 (ax+by=m) 有整数解,我们称这个等式为裴蜀等式,其有解时必然有无穷多个解,每一组解 (x,y) 被称为裴蜀数,可以使用拓展欧几里得算法来求解裴蜀数

    证明

    与下方扩展欧几里得算法的推导方法类似,此处就不再赘述,请接着往下看


    扩展欧几里得算法

    扩展欧几里得算法就是利用欧几里得算法原理推导出的求解裴蜀等式的解的算法

    推导

    对于 (ax+by=gcd(a,b))

    (b=0) 时,显然 (x=1,y=0) 满足等式

    (b>0) 时,不妨设有 (ax_1+by_1=gcd(a,b))(bx_2+(a\%b)y_2=gcd(b,a\%b))

    根据欧几里得算法的原理 (gcd(a,b)=gcd(b,a\%b)) ,可以得出

    [ax_1+by_1=bx_2+(a\%b)y_2 ]

    可以将 (a\%b) 展开为 (a-blfloorfrac{a}{b} floor) ,原式就可以变形为

    [ax_1+by_1=bx_2+(a-blfloorfrac{a}{b} floor)y_2 ]

    整理得

    [x_1a+y_1b=y_2a+(x_2-lfloorfrac{a}{b} floor y_2)b ]

    根据多项式恒等定理可以得出

    [x_1=y_2,y_1=x_2-lfloorfrac{a}{b} floor y_2 ]

    这样就知道了求解 (x_1,y_1) 的方法:通过递归,在 (x_2,y_2) 的基础上算出 (x_1,y_1) ,当递归到 当 (b=0) 时,显然 (gcd(a,b)=a),所以有 (x=1,y=0) ,递归结束

    c++ code

    int exgcd(int a,int b,int &x1,int &y1)
    {
        if(!b)//递归边界
        {
            x1=1,y1=0;
            return a;
        }
        int x2,y2;
        int r=exgcd(b,a%b,x2,y2);//递归
        x1=y2,y1=x2-(a/b)*y2;//使用结论
        return r;
    }
    

    补充

    我们上面的方法只算出了 (ax+by=gcd(a,b)) 的一组特解,对于更一般的方程 (ax+by=c) ,它有解当且仅当 (gcd(a,b)|c) ,我们把算出的特解都乘以 (frac{c}{gcd(a,b)}) 就是 (ax+by=c) 的一组特解

    那么怎么将这一组特解推广到通解呢?

    对于方程 (ax+by=gcd(a,b)) ,考虑把方程中的 (x) 加上一个数 (k_1),把 (y) 减去一个数 (k_2),只要保证原方程仍成立那么 (x+k_1,y-k_2) 就是一组新的解

    把方程写出

    [a(x+k_1)+b(y-k_2)=gcd(a,b) ]

    拆开括号并整理

    [ax+by+ak_1-bk_2=gcd(a,b) ]

    可以看出满足 (ak_1=bk_2) 时原方程仍成立,发现 (ak_1,bk_2) 都一定是 (a,b) 的公倍数,所以有

    [ak_1=bk_2=t*lcm(a,b),tinmathbb{Z} ]

    因此寻找一组新的解只要将 (x) 加上 (frac{b}{gcd(a,b)}) ,将 (y) 减去 (frac{a}{gcd(a,b)}) 就可以了

    综上,方程 (ax+by=c) 的通解可以表示为:

    [x=frac{c}{gcd(a,b)}x_0+kfrac{b}{gcd(a,b)},y=frac{c}{gcd(a,b)}y_0-kfrac{a}{gcd(a,b)} ,kinmathbb{Z} ]

    在实际应用时,为了得到最小正整数解,可以让 (x=left(left(frac{c}{gcd(a,b)}x_0 ight)\%frac{b}{gcd(a,b)}+frac{b}{gcd(a,b)} ight)\%frac{b}{gcd(a,b)}) ,对于 (y) 同理

    应用

    求乘法逆元

    (axequiv 1pmod p) 其中 (gcd(a,p)=1),那么我们就称 (x)(a) 在模 (p) 意义下的乘法逆元

    (axequiv 1pmod p) 的解就相当于求 (ax+py=1) 的解,使用扩欧即可,最后的结果模 (p) 就可以算出 (a) 在模 (p) 意义下的乘法逆元


    该文为本人原创,转载请注明出处

    博客园传送门

    洛谷传送门

  • 相关阅读:
    用Creator实现一个擀面的效果
    游戏开发中的多语言处理
    Docker(六)容器数据卷
    Docker(五)Docker镜像讲解
    Docker(四)Docker镜像安装
    Docker(三)Docker常用命令
    Docker(二)Docker配置
    nginx 与 tomcat 组合搭建web服务
    Zookeeper 使用
    tomcat-manager 设置
  • 原文地址:https://www.cnblogs.com/cmy-blog/p/exgcd.html
Copyright © 2020-2023  润新知