数论(一) 欧几里得算法与扩展欧几里得算法

本文介绍了欧几里得算法及其扩展版,详细讲解了算法的概述、正确性证明、复杂度分析和代码实现。同时探讨了扩展欧几里得算法的解的存在性、通解表示及应用,包括线性丢番图方程、线性同余方程的求解以及乘法逆元的计算。
摘要由CSDN通过智能技术生成

1 欧几里得算法(Euclidean algorithm)

1.1 概述

欧几里得算法,又称辗转相除法,是用于求两个不全等于0的非负整数的最大公约数的算法。
一般用 g c d ( a , b ) gcd(a,b) gcd(a,b) 表示 a a a b b b 的最大公约数,其中 gcd 是 Greatest Common Divisor 的缩写。

欧几里得算法的核心思想可以归结为一个简短而又优雅的式子—— g c d ( a , b ) = g c d ( b , a   m o d   b ) gcd(a,b)=gcd(b,a \bmod b) gcd(a,b)=gcd(b,amodb)。(默认 a ≥ b a \ge b ab)

通过这样的一个式子,我们可以把原问题的规模不断缩小,即一直递归直到到达 base case (即 b = 0 b=0 b=0 )为止。当 b = 0 b=0 b=0 时显然有 g c d ( a , 0 ) = a gcd(a,0)=a gcd(a,0)=a,此时 base case 中的 a a a 值即为原问题中的 a a a b b b 的最大公约数。

下面证明为何 g c d ( a , b ) = g c d ( b , a   m o d   b ) gcd(a,b)=gcd(b,a \bmod b) gcd(a,b)=gcd(b,amodb) 成立。

1.2 正确性证明

g 0 = g c d ( a , b ) g_0=gcd(a,b) g0=gcd(a,b),则 g 0 ∣ a g_0 \mid a g0a g 0 ∣ b g_0 \mid b g0b
g 1 = g c d ( b , a   m o d   b ) g_1=gcd(b,a \bmod b) g1=gcd(b,amodb),则 g 1 ∣ b g_1 \mid b g1b g 1 ∣ ( a   m o d   b ) g_1 \mid (a \bmod b) g1(amodb)

因为 a = ⌊ a / b ⌋ b + ( a   m o d   b ) a= \lfloor a/b \rfloor b+(a \bmod b) a=a/bb+(amodb),而 g 1 g_1 g1 同时整除 b b b ( a   m o d   b ) (a\bmod b) (amodb),故有 g 1 ∣ a g_1 \mid a g1a
g 1 ∣ a g_1 \mid a g1a g 1 ∣ b g_1 \mid b g1b 以及 g 0 g_0 g0 a a a b b b 的最大公约数的事实,可得知 g 1 ∣ g 0 g_1 \mid g_0 g1g0

因为 a   m o d   b = a − ⌊ a / b ⌋ b a \bmod b=a-\lfloor a/b \rfloor b amodb=aa/bb,而 g 0 g_0 g0 同时整除 a a a b b b,故有 g 0 ∣ ( a   m o d   b ) g_0 \mid (a \bmod b) g0(amodb)
g 0 ∣ b g_0 \mid b g0b g 0 ∣ ( a   m o d   b ) g_0 \mid (a \bmod b) g0(amodb) 以及 g 1 g_1 g1 b b b ( a   m o d   b ) (a \bmod b) (amodb) 的最大公约数的事实,可得知 g 0 ∣ g 1 g_0 \mid g_1 g0g1

因为 g 1 ∣ g 0 g_1 \mid g_0 g1g0 g 0 ∣ g 1 g_0 \mid g_1 g0g1,故有 g 0 = g 1 g_0=g_1 g0=g1

证毕。

1.3 复杂度分析

随便 google 一下就能找到不少借助 Fibonacci 数列得出复杂度为 O ( log ⁡ n ) \mathcal{O}(\log n) O(logn) 的帖子。

这里介绍另一种稍微容易一点的分析方法。

r k r_k rk 为进行了 k k k 次取模后的余数,并用 r 0 r_0 r0 表示 b b b,则有:
a   m o d   r 0 = r 1 r 0   m o d   r 1 = r 2 ⋮ r k   m o d   r k + 1 = r k + 2 ⋮ a \bmod r_0=r_1\\r_0 \bmod r_1=r_2\\\vdots\\r_k \bmod r_{k+1}=r_{k+2}\\\vdots amodr0=r1r0modr1=r2rkmodrk+1=rk+2

观察若干步骤后会发现 —— r k + 2 ≤ 1 / 2 r k r_{k+2} \le 1/2r_k rk+21/2rk,即递归过程每加深两层,问题规模必小于等于原来的一半。

下面给出证明。

  1. r k + 1 ≥ 1 / 2 r k r_{k+1} \ge 1/2r_k rk+11/2rk,则有 r k − r k + 1 ≤ 1 / 2 r k r_k-r_{k+1} \le 1/2r_k rkrk+11/2rk,故 r k + 2 = r k   m o d   r k + 1 ≤ r k − r k + 1 ≤ 1 / 2 r k r_{k+2}=r_k \bmod r_{k+1} \le r_k-r_{k+1} \le 1/2r_k rk+2=rkmodrk+1rkrk+11/2rk
  2. r k + 1 < 1 / 2 r k r_{k+1} < 1/2r_k rk+1<1/2rk,则有 r k + 2 = r k   m o d   r k + 1 < r k + 1 ≤ 1 / 2 r k r_{k+2}=r_k \bmod r_{k+1}<r_{k+1} \le 1/2r_k rk+2=rkmodrk+1<rk+11/2rk

综上,必有 r k + 2 ≤ r k r_{k+2} \le r_k rk+2rk

证毕。

故 Euclidean algorithm 的时间复杂度为 O ( log ⁡ n ) \mathcal{O}(\log n) O(logn)

1.4 代码

LL gcd(LL a, LL b)
{
   
    if (b > a) swap(a, b);
    if (b == 0) return a;
    return gcd(b, a % b);
}

2 扩展欧几里得算法(extended Euclidean algorithm)

2.1 概述

扩展欧几里得算法实际上就是在欧几里得算法的基础上给出了如何构造 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b) 的解的方法,其中 a a a b b b 为不全等于0的两个非负整数, x x x y y y 为任意整数。

2.2 算法流程及相关证明

2.2.1 解的存在性证明

下面使用构造法来证明解的存在性

  1. b = 0 b=0 b=0 时,显然有 g c d ( a , b ) = a gcd(a,b)=a gcd(a,b)=a,故一组解为 x = 1 , y = 0 x=1,y=0 x=1,y=0

  2. b ≠ 0 b \ne 0 b=0 时,设 a x 0 + b y 0 = g c d ( a , b ) ax_0+by_0=gcd(a,b) ax0+by0=gcd(a,b) b x 1 + ( a   m o d   b ) y 1 = g c d ( b , a   m o d   b ) bx_1+(a \bmod b)y_1=gcd(b,a \bmod b) bx1+(amodb)y1=gcd(b,amodb)

    g c d ( a , b ) = g c d ( b , a   m o d   b ) gcd(a,b)=gcd(b,a \bmod b) gcd(a,b)=gcd(b,amodb) 可得 a x 0 + b y 0 = b x 1 + ( a   m o d   b ) y 1 ax_0+by_0=bx_1+(a \bmod b)y_1 ax

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值