扩展欧几里得算法【原理+编码】

一、问题描述

已知两个整数m和n,求mx + ny = gcd(m, n)。

二、知识引入

贝祖定理:m>=0, n>=0, 且m,n\epsilonZ    =>   E x, y \epsilon Z, 使 mx + ny =gcd(m,n)

定理证明:1)设m=n=0,则gcd(m, n)=0,显然定理成立。
                  2)设m != 0 ,集合A={ mx+ny | x, y  \epsilon Z },则 A \subset Z.
                        =>   令集合P=A\capN,则P={z | z >= 0 }. 【证明P\notin\O
                        =>   设
d是P中最小的正整数,则 E x0, y0 \epsilon Z , 使 mx0 + ny0 = gcd(m, n) = d.
                        =>   设d|m = q...r,即m=d*q+r,  d>r>=0.
                        =>   r = m - d * q = m - (mx0 + ny0)*q = m(1-x0) - n(qy0) 
                        =>   r \epsilon  P, 又d>r与d是P中最小的正整数矛盾
                        =>   r = 0.
                        =>   m=d*q, 同理可证n=d*p,即
d是m和n的公约数
                        =>   设c是m和n的任一公约数,则 m=c*c',  n=c*c''.
                        =>   d = mx0 + ny0 = (c*c')x0 + (c*c'')y0 = c ( c'x0 + c''y0 ).
                        =>   d >= c, 即
d大于等于m和n的任一公约数
                        =>   d=gcd(m,n)

证明P\notin\O
                  1)设(x, y) = (\pm1,0),则mx+ny = \pmm,即 \pm\epsilon A,亦即
A中至少有一个正数 |m|.
                  2)因为P=A \cap N, |m| \epsilon A, |m| \epsilon N,所以|m| \epsilon P. 即P\notin\O.
           P\notin\O得证。
定理得证。

三、解题思路

             已知 mx + ny = gcd(m, n),  且gcd(m, n) = gcd(n, m%n). (m>=n)
             => mx + ny = gcd(m, n) = gcd(n, m%n) = nx' + (m%n)y'
             => mx + ny = nx' + (m%n)y'
             => mx + ny = nx' + (m-n*\left \lfloorm/n\right \rfloor\right \rfloor\rfloor )y'
             => mx + ny = my' + n(x'-\left \lfloorm/n\right \rfloor\right \rfloor\rfloory')
             => x=y',   y=x' - \left \lfloorm/n\right \rfloor\right \rfloor\rfloory'
             => 即mx + ny = gcd(m,n)的解(x, y),由nx + (m%n)y = gcd(n, m%n)的解(x', y')求出

             然后可得出求解递归式:
                    设求解函数为F(m, n, x, y) : mx + ny = gcd(m, n)
                    则 F(m, n, x, y) = F(n, m%n, y', x'- \left \lfloorm/n\right \rfloor\right \rfloor\rfloory')
                         F(d, 0, 1, 0): gcd(m,n)=gcd(d,0)=d

四、编程求解

int EuclidXY(int m, int n, int *x, int *y)
{
    //欧几里得算法求gcd(m, n),同时求解mx+ny=gcd(m,n)
    //递归算法
    //输入:两个不全为0的非负整数m,n, 整数x和y的地址
    //输出:m,n的最大公约数,gcd(0,0)=0
    if(m < n)
    {
        int temp = n;
        n = m;
        m = temp;
    }
    if(n==0)
    {
        *x = 1;
        *y = 0;
        return m;
    }
    //法一
    //int r=EuclidXY(n, m%n, x, y);
    //int temp = *y;
    //*y = *x - m/n * (*y);
    //*x = temp;
    //法二
    int r = EuclidXY(n, m%n, y, x);
    *y -= m/n * (*x);
    return r;
}

五、推广

  • 定理一:ax + by = c有解,当且仅当c%gcd(a,b)=0
           证明:设c%gcd(a,b)=0 ………………………证明c%gcd(a,b)==0时有解
                      => c = gcd(a,b) * k
                      => 又ax + by = gcd(a,b)有解
                      => a*k*x + b*k*y = k*gcd(a,b) = c有解
                      => 原式解为(kx, ky), 其中(x,y)是ax+by=gcd(a,b)的解

                      设c%gcd(a,b)!=0时有解………………证明c%gcd(a,b) != 0时无解
                      => c=gcd(a,b)*k+r,gcd(a,b)>r>0
                      => 又ax'+by'=gcd(a,b)
                      => c=(ax' + by')*k+r
                      => c=a(kx')+b(ky')+r
                      => 令x=kx', y=ky'
                      => 则c=ax+by+r
                      => 又gcd(a,b)<=min{a,b}
                      => 0                   => 所以c=ax+by+r不能化为c=a(x+e)+by, r=ae,e是正数的形式
                      => 与题设c=ax+by有解矛盾
           证毕
  • 定理二:若ax + by = c有解,x最小非负整数解为(x+b1*t)%b1, b1=b/gcd(a,b)
           证明:因为ax+by=c有解
                      所以c % gcd(a,b) = 0
                      令a1=a/gcd(a,b),  b1=b/gcd(a,b), c1=c/gcd(a,b)
                      所以原式 <=> a1*x + b1*y = c1    (两边同时除gcd(a,b)) 
                      设一组解为(x', y')
                      由定理三知所有解(x, y) = (x'+b1*t,  y'-a1*t)        (gcd(a1,b1)=1)
                      所以x是一组间隔为b1的整数,
                      min(x)=(x'+b1*t)/b1
  • 定理三:已知ax+by=gcd(a,b)的一组解为(x', y'),则其所有解为x=x'+b/gcd(a,b)*t,   y=y'-a/gcd(a,b)*t,  t是整数
           证明:已知ax' + by' = gcd(a,b)
                      => 同时在式子两边加上能同时整合到ax'和by'上的最小整数:ab/gcd(a,b)
                      => ax' + by' + ab/gcd(a,b) = gcd(a,b) + ab/gcd(a,b)
                      => ax'+ tab/gcd(a,b) + by' -tab/gcd(a,b) = gcd(a,b)     (t是整数)
                      => a(x'+tb/gcd(a,b)) + b(y'-ta/gcd(a,b)) = gcd(a,b)
                      => x = x' + tb/gcd(a,b),  y=y'-ta/gcd(a,b)
            这其实很不严谨

 

你可能感兴趣的:(扩展欧几里得算法【原理+编码】)