最大公约数问题(扩展)

引言

我们知道,求最大公约数可以用欧几里德方法。d = gcd(a, b) = gcd(b, a%b)。

那么我们是否可以快速求出以下等式的系数x和y呢?

d = gcd(a,b) = x*a + y*b

(注:系数x和y是唯一的。参见introduction to algorithm中的number theory章节)

问题

给出两个整数,求其最大公约数以及唯一的系数。即:

d = gcd(a,b) = x*a + y*b,给定a,b,求(d, x, y).

基本迭代关系

d = gcd(a, b) = x * a + y * b

d' = gcd(b, a%b) = x' * b + y' * (a%b) = x' * a + y' * (a - (a/b)*b) = y' * a + (x' - (a/b)y') * b

d = d'

==>

(d, a, b) = (d', y', x' - y'*(a/b))

(边界条件是b=0是,返回(a, 1, 0)

代码

#!/usr/bin/env python
import sys
def euclid(a, b):
    if b==0:
        return a
    else:
        return euclid(b, a%b)

def gcd(a, b):
    a = abs(a)
    b = abs(b)
    return euclid(a, b)

# extended euclid algorithm
# d = gcd(a,b) = xa+yb
# get gcd and the coefficients
def extended_euclid(a, b):
    if b==0:
        return (a, 1, 0)
    (d_low, x_low, y_low) = extended_euclid(b, a%b);
    (d, x, y) = (d_low, y_low, x_low - a/b*y_low);
    return (d, x, y)

def gcd2(a, b):
    a = abs(a)
    b = abs(b)
    return extended_euclid(a, b)

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print 'gcd.py num1 num2'
        sys.exit(1)
    else:
        num1 = int(sys.argv[1])
        num2 = int(sys.argv[2])
        (d, x, y) = gcd2(num1, num2)
        print '%d = gcd(%d,%d) = %d*%d + %d*%d'% \
            (d, num1, num2, x, num1, y, num2)

测试示例

./gcd.py 27 21
3 = gcd(27,21) = -3*27 + 4*21

./gcd.py 567432 3892347
27 = gcd(567432,3892347) = 20078*567432 + -2927*3892347

你可能感兴趣的:(算法,扩展,最大公约数)