扩展欧几里德算法(gcd扩展使用)

首先让我们先来普及一下,关于gcd的知识,这里几个字就可以搞定,gcd(a,b)就是指a,b的最大公约数,我靠,你可能会说这个有什么用呢?

不要着急,我们马上就会进行讲解:

首先先来普及一些基本概念:

首先他们必须满足贝祖等式(好高大上的名字啊!): ax+by = gcd(a, b)。

于是由这个定理,我们成功推出了:(说实话我TM也没有听懂是怎么推的,呵呵!)

所以,我们由gcd函数的知识,可以成功的推出,如下两个递归时的方程:

ax+by=gcd(a,b);
因为a=a%b+(a/b)*b;
带入化简后:b((a/b)*x+y)+(a%b)*x=gcd(b,a%b);

下面为证明过程:

   设:a>b。
  推理1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
        //-------------------------------------------------------------
  推理2,ab!=0 时
  设 ax+by=gcd(a,b);//important
  bx1+(a%b)y1=gcd(b,a%b);
  根据正常欧几里德原理有 gcd(a,b)=gcd(b,a%b);
  则:ax+by=bx1+(a%b)y1;
    因为a=a%b+(a/b)*b;代入
  即:ax+by=bx1+(a-(a/b)*b)y1=ay1+bx1-(a/b)*by1=ay1+b(x1-(a/b)*y1);
  由此得:x=y1 ,y=x1-(a/b)*y1;
    //-------------------------------------------------------------
  这样我们就得到了求解 x,y 的方法:x,y 的值基于 x1,y1.
   \上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。

这个推理应该非常的完美了吧!

我认为这份推理很不错的诠释了我给lry讲了半天的东西是怎么来的(因为他设了两个变量),所以讲的非常清楚,点赞!

那么相信大家gcd应该是没有什么问题了:

下面是代码实现:

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

附件(网络资料):

听说有非递归版!

http://anh.cs.luc.edu/331/notes/xgcd.pdf

http://math.cmu.edu/~bkell/21110-2010s/extended-euclidean.html

如果你还是没有看懂

下面有从《计算机程序设计艺术》转载的证明方法,仅供参考:

 证明(1):
  算法首次转到E2时,由上表,显然等式成立。
  步骤 E2,E3 并不会改变等式的正确性。
  所以只需要证明步骤 E4 不改变他们的正确性就可以了。

  执行 E4 之前,
      a'm + b'n = c    (*)
      am + bn = d      (**)
  成立。
  a'm + b'n = c = qd + r;
  a'm + b'n - q(am + bn) = r;
  (a' - qa)m + (b' - qb)n = r  (***)

  执行 E4 之后,c←d, d←r, t←a', a'←a, a←t-qa, t←b', b'←b, b←t-qb;
  所以
  (**)变为 a' + b' = c
  (***)变为 am + bn = d
  所以步骤 E4 不改变等式的正确性,得证。

下面强势给出非递归版代码:(我也好像有点懂!)

int exgcd(int m, int n, int &x, int &y) {
    if (n == 0) {
        x = 1; y = 0;
        return m;
    }
    int a, a1, b, b1, c, d, q, r, t;
    a1 = b = 1;
    a = b1 = 0;
    c = m; d = n;

    q = c/d; r = c%d;
    while (r) {
        c = d;
        d = r;
        t = a1;
        a1 = a;
        a = t - q * a;
        t = b1;
        b1 = b;
        b = t - q * b;

        q = c/d;
        r = c%d;
    }
    x = a; y = b;
    return d;
}

(以上代码为转载)

相关练习题

P1082 同余方程

另一篇洛谷博客:

简单的欧几里德拓展

你可能感兴趣的:(数学)