欧几里得算法
假设有两个非负整数 a , b a,b a,b,并且 a , b a,b a,b都不等于0,那么 a , b a,b a,b的最大公约数等于其中较小的数和 a , b a,b a,b相除的余数的最大公约数。
用公式表达为 g c d ( a , b ) = g c d ( b , a ( m o d b ) ) gcd(a,b)=gcd(b,a\pmod{b}) gcd(a,b)=gcd(b,a(modb)),其中 a > = b a>=b a>=b。
证明过程
假设 k 可以同时整除 a , b 。 ∵ a > = b ∴ a = k b + r ∴ k 也可以整除 r 。 ∴ g c d ( a , b ) = g c d ( b , a ( m o d b ) ) 成立。 \begin{aligned} 假设 k 可以同时整除a,b。\\ &\because a>=b \\ &\therefore a=kb+r \\ &\therefore k \quad 也可以整除\quad r 。\\ &\therefore gcd(a,b)=gcd(b,a\pmod{b}) \quad 成立。 \end{aligned} 假设k可以同时整除a,b。∵a>=b∴a=kb+r∴k也可以整除r。∴gcd(a,b)=gcd(b,a(modb))成立。
代码实现
def gcd_by_euclidean_algorithm(a: int, b: int) -> int:
while b != 0:
a, b = b, a % b
return a
# expect 1
print(gcd_by_euclidean_algorithm(3, 4))
# expect 4
print(gcd_by_euclidean_algorithm(12, 4))
# expect 6
print(gcd_by_euclidean_algorithm(18, 24))
扩展欧几里得算法
已知正整数 a , b a,b a,b,求解一组 x , y x,y x,y,使它们满足贝祖等式 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)。
特别的,当 a ⊥ b a\perp b a⊥b时,求解的 x x x为 a a a模 b b b的逆元,即 a x ≡ 1 ( m o d b ) ax\equiv 1\pmod{b} ax≡1(modb)。
扩展欧几里得算法的代码实现
扩展欧几里得算法实质上是求解贝祖等式的解。
def extended_gcd(a: int, b: int) -> int:
# 当a为0时,贝祖等式的系数x=0,y=1,最大公约数为b
if a == 0:
return b, 0, 1
# 递归求取最大公约数和贝祖系数
d, x, y = extended_gcd(b % a, a)
# 更新系数
return d, y - (b // a) * x, x
根据扩展欧几里得算法求解模逆元
代码实现如下:
def mod_inverse(a, m):
gcd, x, y = extended_gcd(a, m)
# 当a,b不互质时,不存在模逆元
if gcd != 1:
raise Exception("Not found mod inverse.")
return x % m
注意: 调用扩展欧几里得算法求得 x x x可能是负数,这时需要对 x x x模 m m m,确保 x x x是一个正数。
求证扩展欧几里得算法中系数公式
扩展欧几里得算法的核心是更新贝祖等式系数的公式,这些公式是基于欧几里得算法的递归性质推导出来的。下面是详细的证明过程:
初始等式: a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b),其中 x , y x,y x,y是贝祖系数。
递归的第二层存在等式: b ( m o d a ) ∗ x 1 + a ∗ y 1 = g c d ( b ( m o d a ) , a ) b\pmod{a} * x_1+a*y_1=gcd(b\pmod{a},a) b(moda)∗x1+a∗y1=gcd(b(moda),a)。
根据欧几里得算法可知: g c d ( a , b ) = g c d ( b ( m o d a ) , a ) = d gcd(a,b)=gcd(b\pmod{a},a)=d gcd(a,b)=gcd(b(moda),a)=d,其中 d d d表示 a , b a,b a,b的最大公约数。
又因为:
b
(
m
o
d
a
)
=
b
−
⌊
b
a
⌋
∗
a
b \pmod{a} = b - \lfloor \frac{b}{a} \rfloor * a
b(moda)=b−⌊ab⌋∗a
将此式子带入第二层的递归的等式中可得:
( b − ⌊ b a ⌋ ∗ a ) ∗ x 1 + a ∗ y 1 = d a ∗ ( y 1 − ⌊ b a ⌋ ∗ x 1 ) + b ∗ x 1 = d (b-\lfloor \frac{b}{a} \rfloor *a)*x_1+a*y_1=d \\ a*(y_1-\lfloor \frac{b}{a} \rfloor *x_1) + b*x_1 = d (b−⌊ab⌋∗a)∗x1+a∗y1=da∗(y1−⌊ab⌋∗x1)+b∗x1=d
因此递归时,两次递归之间的系数关系为:
x = y 1 − ⌊ b a ⌋ ∗ x 1 y = x 1 \begin{aligned} x&=y_1-\lfloor \frac{b}{a} \rfloor *x_1 \\ y&=x_1 \end{aligned} xy=y1−⌊ab⌋∗x1=x1