引言
我们知道,求最大公约数可以用欧几里德方法。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