欧几里得算法和扩展欧几里得算法

1.欧几里得算法

//递归版本
int gcd(int a ,int b){
    return b == 0 ? a :gcd(b , a % b);
}

//非递归版本
while(b != 0){
    temp = a;
    a = b;
    b = t % a;  
}

2.扩展欧几里得算法

1.递归模板
//递归版本模板
int extgcd(int a , int b , int &x , int &y){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    int d = extgcd(b , a % b , x , y);
    int t = x;
    x = y;
    y = t - a / b * y;
    return d;
}
2.扩展欧几里得问题描述及分析

问题:求整数x和y使得ax+by=t。
分析:我们可以发现如果gcd(a , b) != t,显然无解。反之,如果gcd(a , b) = t , 就可以通过扩展原来的辗转相除法来求解。事实上,一定存在整数对(x , y)使得ax+by=gcd(a , b),并可以用同样的算法求得。

例:求整数x和y使得127x+97y=1

解法一:利用类似辗转相除的做法

先分解:
127 = 97 * 1 + 30
97 = 30 * 3 +7
30 = 7 * 4 + 2
7 = 2 * 3 + 1
再移动:
30 = 127 + 97 * (-1)
7 = 97 + 30 * (-3)
2 = 30 + 7 * (-4)
1 = 7 + 2 * (-3)
最后回代:
1 = 7 + 2 * (-3)
1 = 7 + (30 +7 * (-4)) * (-3) = 7 * 13 + 30 * (-3)
1 = (97 +30 * (-3)) * 13 + 30 * (-3) = 97 * 13 + 30 * (-42)
1 = 97 * 13 + (127 + 97 * (-1)) * (-42) = 127 * (-42) + 97 * 55
解得:x = -42 , y = 55

解法二:手动模拟扩展欧几里得算法(对照上面的偶看欧几里得模板来看下面的过程)

递归:
第一层:127x0 + 97y0 = 1
第二层:97x1 +30y1 = 1
第三层:30x2 +7y2 = 1
第四层:7x3 +2y3 = 1
第五层:2x4 +1y4 = 1
第六层:1x5 +0y5 = 1 ====> x5 = 1 , y5 = 0 , 返回值:1
第五层:====> d = 1 , x4 = 0 , y4 = 1 - 2 / 1 * 0 = 1 ,返回值:1
第四层:====> d = 1 , x3 = 1 , y3 = 0 - 7 / 2 * 1 = -3,返回值:1
第五层:====> d = 1 , x2 = -3 , y2 = 1 - 30 / 7 * (-3) = 13,返回值:1
第五层:====> d = 1 , x1 = 13 , y1 = (-3) - 97 / 30 * (13) = (-42),返回值:1
第五层:====> d = 1 , x0 = (-42) , y0 = 13 - 127 / 97 * (-42) = 55,返回值:1
解得:x = -42 , y = 55 , 其中,函数的返回值就是两个系数的最大公约数。

你可能感兴趣的:(算法)