zoukankan      html  css  js  c++  java
  • 再探最大公约数

    [ ewcommand{lcm}{mathrm{lcm}\,} ]

    说明: 在不定方程之前,数集指的是正整数集; 全文以 (\%) 表示取模运算。

    从更相减损术说起

    可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
    

    最小公倍数定义为最大的 (a) ,使得 (a|b)(a|c) 。记 (gcd(b,c)=a)

    那么更相减损术就是说 (gcd(a,b)=gcd(a-b,b))(a>b) ); (gcd(a,b)=a=b) ,并且迭代有限次数后,一定能得到 (a=b) 的情况。

    • 感性理解
      (a)(b) 都是由长度为 (gcd(a,b)) 的块组成的。那么减一减一定还是 (gcd(a,b)) 长的块的整数倍。

    • 证明
      (a)(b) 相等情况证明略,操作步数有限性证明略。
      (gcd(a,b)=k) ,那么 (a=a'k)(b=b'k) 。由于 (a>b) ,所以 (a'>b') 。那么 (a - b=(a'-b')k eq 0) 。所以 (k|a-b) ,那么 (gcd(a-b,b)geqslant k)
      而若 (gcd(a-b,b)>k) ,那么存在 (k'>1) ,使得 (kk'|b)(kk'|a-b) 。那么 (k'|b)(k'|a-b) 。那么 (k'|(a-b)+b) ,即 (k'|a) 。所以 (kk'|a)(kk'|b)(kk'>k) 。这与 (gcd) 的最大性矛盾。所以 (gcd(a-b,b)leqslant gcd(a,b))
      综上所述, (gcd(a-b,b)=gcd(a,b))

    更快的实现:辗转相除法

    (a) 远大于 (b) 的时候,更相减损术会花很多的时间让 (a) 不断地减去 (b) 。我们可以想办法加速这个过程——即用取余操作代替减法操作。
    辗转相除法可以这样描述 :

    假设 (ageqslant b) ,那么 (gcd(a,b)=gcd(b,a\%b))(b mid a)(gcd(a,b)=b)(b|a)

    而由于 (a\%b leqslant lfloorfrac{a}{2} floor) ,所以辗转相除法的时间复杂度是 (log) 级别的。

    int Gcd(int a, int b)
    {
        if(a % b == 0) return a;
        return Gcd(b, a % b);
    }
    
    int Gcd(int a, int b)
    {
        int m = a % b;
        while (m)
        {
            a = b;
            b = m;
            m = a % b;
        }
        return b;
    }
    

    最大公约数的性质:裴蜀定理

    裴蜀定理(或贝祖定理,Bézout's identity)得名于法国数学家艾蒂安·裴蜀。说明了对任何整数 (a)(b) 和它们的最大公约数 (d) :若 (a) , (b) 是整数,且 (gcd(a,b)=k) ,那么对于任意的整数 (x)(y) , (ax+by) 都一定是 (k) 的倍数;特别地,一定存在整数 (x) , (y) ,使 (ax+by=k) 成立。

    证明:
    (gcd(a,b)=k) ,所以 (k|a)(k|b) 。由整除的性质,对于任意 (x,yin Z)(k|ax+by)
    (ax+by) 的最小正整数值为 (s)(q = lfloorfrac{a}{s} floor)(r=a \% s=a-q(ax+by)=a(1-qx)+b(-qy))。也就是说, (r) 也是 (ax+by) 的某个取值。而由于 (s) 的最小性,(r=0) 。即 (s|a) 。同样的,有 (s|b) 。又因为 (ax+by)(k) 的倍数,所以 (s=k)

    如何构造这样一组解?:扩展欧几里得算法

    (b|a) 时, (gcd(a,b)=b)(x=0,y=1) 是方程 (ax+by=b) 的一组解。
    如果我们已经知道了 (x',y') 是方程 (bx+(a\%b)y=gcd(a,b)) 的一组解,那么有:

    [bx'+(a-blfloorfrac{a}{b} floor)y'=gcd(a,b)\ bx'+ay'-blfloorfrac{a}{b} floor y'=gcd(a,b)\ ay'+b(x'-lfloorfrac{a}{b} floor x')=gcd(a,b) ]

    (x=y')(y=x'-lfloorfrac{a}{b} floor x') 就能得到 (ax+by=gcd(a,b)) 的一组解。

    void exgcd(int a, int b, int &x, int &y, int &gcd)
    {
        if (b == 0)
        {
            x = 1;
            y = 0;
            gcd = a;
            return;
        }
        exgcd(b, a % b, y, x, gcd);
        y -= a / b * x;
        return;
    }
    

    不定方程 (ax+by=c) 的最小整数解

    通解形式

    显然,如果 (gcd(a,b) mid c) ,方程无解。

    先考虑方程 (ax+by=gcd(a,b)) 。为了让 (ax+by=gcd(a,b))(ax)(by) 的值要同时变化 (lcm(a,b)) 。所以通解为

    [x=x'+kfrac{b}{gcd(a,b)}\ y=y'-kfrac{a}{gcd(a,b)} ]

    其中 (x')(y') 是一组特解。
    (p=frac{b}{gcd(a,b)}) 那么 (x=(x' \% p +p ) \%p) 就是 (x) 的最小正整数解。

    然后在看方程 (ax+by=c) 。不难发现它的通解是

    [x=x'frac{c}{gcd(a,b)}+kfrac{b}{gcd(a,b)}\ y=y'frac{c}{gcd(a,b)}+kfrac{a}{gcd(a,b)} ]

    同样的,令 (p=frac{b}{gcd(a,b)}) 。为了防止溢出,可以这样算:

    [x=(x'\%p) imes(frac{c}{gcd(a,b)}) \% p ]

    最后 (x) 可能为负数,所以 (x=(x+p)\%p) 即可。

    扩展欧几里得算法的应用:乘法逆元

    我的博客

    推荐练习题

    CF1244C The Football Season

  • 相关阅读:
    Tomcat Jboss,jetty,Apache WebLogic区别与比较(阿里面试)
    zookeeper 负载均衡 核心机制-实现原理 包含ZAB协议(滴滴,阿里面试)
    六大Web负载均衡原理与实现
    LVS(Linus Virtual Server):三种IP负载均衡方式比较+另三种Web负载均衡方式
    JTable动态刷新数据
    java当中的定时器的4种使用方式
    java如何判断编码是否是utf8编码
    Java多线程-线程的同步与锁
    java中需要用equals来判断两个字符串值是否相等
    libcurl使用easy模式阻塞卡死等问题的完美解决---超时设置
  • 原文地址:https://www.cnblogs.com/chy-2003/p/11700405.html
Copyright © 2011-2022 走看看