• 欧几里得算法


    【辗转相除法求GCD】

    欧几里得法求GCD效率较辗转相减法求GCD而言效率要高得多。

    算法原理:gcd(a,b)=gcd(b,a mod b)

    首先我们可以假设a=kb+ra=k∗b+r(其中的r代表着a/b的余数,也就是a%b的结果)

      1.首先我们假设d是a和b的最大公约数,则我们可以知道 a可以整除d,表示为a|b,b也可以整除d,表示为b|d,由于r=akbr=a−k∗b 其中a是d的倍数,而且b也是d的倍数,那我们可以得到其实r也是d的倍数,换句话说r也是可以整除d.

      2.接下来我们假设d是b和r的最大公约数,则我们可以知道b可以整除d,表示为b|d,r也可以整除d,表示为r|d,由于a=kb+ra=k∗b+r其中b是d的倍数,而且r也是d的倍数,那我们可以得知其实a也是d的倍数,换句话说a也是可以整除d.

    通过以上的充分必要式的证明方法,我们可以得到:gcd(a,b)=gcd(b,a%b)

    【gcd模板】

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

    【扩展欧几里得算法】

    解决问题:ax + by = gcd(a,b)的一组整数解x0 y0

    算法原理:

    (1)当b = 0时,很显然 x = 1,y = 任意整数。不妨x = 1, y = 0

    (2)设 bx' + (a%b) y' = gcd(b , a%b)

    由欧几里得算法:gcd(a,b)=gcd(b,a%b)

    从而:ax + by = bx' + (a%b) y'; 即 ax + by = bx' + (a - a/b*b)y'

    整理成关于a,b的不定方程:ax + by = ay' + b(x' - a/by'),系数对应相等得到:

    x = y' ;

    y = x' - a/by'

    试想:如果不断迭代下去,直至b = 0,然后运用(1)的结果直接得到(x' = 1, y '= 0)反推回去,是不是就能够得到初始的x,y的值了?

    int ex_gcd(int a,int b,int &x,int &y)
    {
        if(b == 0)
        {
            x = 1;
            y = 0;
            return a;
        }
        int r = ex_gcd(b,a%b,x,y);
    int t = x;//保存上一次的x' x = y;//本次的x是上一次的y' y = t - a/b*y;//本次的y是上一次的x' - a/b*y'
    return r; }

    【定理总结】

    (1)二元一次不定方程 ax + by = k有解的充要条件是 gcd(a,b) | k

    (2)若ax + by = gcd(a,b)的一组特解是x0 ,y0,则通解:

    x = x0 + b/gcd(a,b) * t ;

    y = y0 -  a/gcd(a,b) * t ,

    方程ax + by = k的解是x,y乘上 k/gcd(a,b),即x = (x0 + b/gcd(a,b) * t) * k/gcd(a,b)

    (3)要求方程ax + by = k的x的最小正整数解,则先求一个x0,y0,令p = b/gcd(a,b) 

    然后令 x = (x0 + p)* k/gcd(a,b), x = (x%p + p)%p.对应的y =(k - a*x) / b

    【例题】

    poj2142

  • 相关阅读:
    业务场景和业务用例场景的区别(作者:Arthur网友)
    svn 安装
    PHP has encountered an Access Violation at
    邀请大象一书的读者和广大网友写关于分析设计、建模方面的自愿者文章
    手机网页 复制信息方法 免费短信
    delphi Inno Setup 制作安装程序
    Special Folders
    Windows mobile上获取输入光标位置
    加壳程序无法准确读输入表的解决办法
    C++ PostMessage 模拟键盘鼠标
  • 原文地址:https://www.cnblogs.com/czsharecode/p/9736800.html
Copyright © 2020-2023  润新知