◆程序笔记◆◇第四期◇扩展欧几里得算法

来源:互联网 发布:tensorflow get shape 编辑:程序博客网 时间:2024/06/06 03:01

Lucky_Glass的程序笔记

第四期-扩展欧几里得算法


欧几里得算法是一种高效的求 gcd(a,b) 的算法,可以通过递推或递归计算。经过验算,我们发现——当a < b时,gcd(a,b)==gcd(a,b-a),否则等于 gcd(b,b-ka) (k为b整除a的值)。但是这样对栈空间的浪费极大,我们可以发现 b-ka 就是b取模a,即 b%a 。现在给出了一个问题——给定 a、b ,求出任意一组整数 x,y ,使得 xa+by==gcd(a,b) 。而求x、y的算法就是扩展欧几里得算法


  1. 扩展欧几里得算法的推导
    根据题意,我们可以令gcd(a,b)=f;则有xa+yb=f,且其中都只包含整数。
    先从特殊的情况开始考虑——当递归到b为0时,则得到 xa+0*y=a ,那么y可以取任意值(这也是会有多组解的原因),但是x只能取1。
    接下来考虑一般的情况。因为 gcd(a,b)=gcd(b,a%b) ,则令 bx’ + (a%b)y’ = gcd(b,a%b) 。那么 bx’ + ( a % b ) y’ = ax + by 。推导到这里,式中出现了一个 mod(取模),那么我们需要把mod拆开。这里用到了一个定义 “[a]”,意思是对a向0取整。那么 C++中的 a%b 用代数式就可以表示为:a - [ a / b ] * b,那么原式改为:
    bx+(a[a/b]b)y=ax+by
    又可改为:
    bx+ay[a/b]by=ax+by
    最后变为:
    ay+b(x[a/b]y)=ax+by
    根据对应项系数相等,则得——对于每一步的x,y都有: x=yy=x[a/b]y

  2. 扩展欧几里得算法的C++实现
    接下来就是将算法代码化。我们可以对我们之前的gcd(a,b)函数进行一些修改,原本的gcd函数为:

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

我们需要将每一步的x、y都代入函数中。则可以应用 “传址” 的方法,在参数表中加入 x、y和sum(该次递归中的 ax+by 的值),即:

int gcd(int &x,int &y,int &sum,int a,int b);

当 b==0 时,则分别将 x、y 赋值为 1 和 0(y也可以赋值为其他数,但0较为方便),sum 赋值为 a 。 b != 0 时,先定义 sx、sy (即 x’ 和 y’),后执行gcd()函数。最后返回时,x 则赋值为 sy ,y则赋值为 sx - a / b * sy。如果不需要求出 gcd(a,b) 的话,函数是可以不返回值的。
3. 样例程序

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

The End

Thanks for reading!

-Lucky_Glass


原创粉丝点击