欧几里得算法和裴蜀定理学习笔记

最大公约数

最大公约数即为 Greatest Common Divisor,常缩写为 gcd。

一组整数的公约数,是指同时是这组数中每一个数的约数的数。 ± 1 \pm 1 ±1 是任意一组整数的公约数。

一组整数的最大公约数,是指所有公约数里面最大的一个。

如果两个数 a a a b b b 满足 gcd ⁡ ( a , b ) = 1 \gcd(a, b) = 1 gcd(a,b)=1,我们称 a a a b b b 互质。

那么如何求最大公约数呢?我们先考虑两个数的情况。


欧几里得算法(辗转相除法)

如果我们已知两个数 a a a b b b,如何求出二者的最大公约数呢?

不妨设 a > b a > b a>b

我们发现如果 b b b a a a 的约数,那么 b b b 就是二者的最大公约数。

下面讨论不能整除的情况,即 a = b × q + r a = b \times q + r a=b×q+r,其中 r < b r < b r<b

我们通过证明可以得到 gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   b ) \gcd(a,b)=\gcd(b,a \bmod b) gcd(a,b)=gcd(b,amodb)

  • 证明
    a = b k + c a=bk+c a=bk+c,显然有 c = a   m o d   b c=a \bmod b c=amodb。设 d ∣ a ,   d ∣ b d \mid a,~d \mid b da, db,则 c = a − b k , c d = a d − b d k c=a-bk, \frac{c}{d}=\frac{a}{d}-\frac{b}{d}k c=abk,dc=dadbk
    由右边的式子可知 c d \frac{c}{d} dc 为整数,即 d ∣ c d \mid c dc 所以对于 a , b a,b a,b 的公约数,它也会是 a   m o d   b a \bmod b amodb 的公约数。
    反过来也需要证明:
    d ∣ b ,   ∣ ( a   m o d   b ) d \mid b,~\mid (a \bmod b) db, (amodb),我们还是可以像之前一样得到以下式子 a   m o d   b d = a d − b d k ,   a   m o d   b d + b d k = a d \frac{a\bmod b}{d}=\frac{a}{d}-\frac{b}{d}k,~\frac{a\bmod b}{d}+\frac{b}{d}k=\frac{a}{d} damodb=dadbk, damodb+dbk=da
    因为左边式子显然为整数,所以 a d \frac{a}{d} da 也为整数,即 d ∣ a d \mid a da,所以 b , a   m o d   b b,a\bmod b b,amodb 的公约数也是 a , b a,b a,b 的公约数。
    既然两式公约数都是相同的,那么最大公约数也会相同。
    所以得到式子 gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   b ) \gcd(a,b)=\gcd(b,a\bmod b) gcd(a,b)=gcd(b,amodb)

既然得到了 gcd ⁡ ( a , b ) = gcd ⁡ ( b , r ) \gcd(a, b) = \gcd(b, r) gcd(a,b)=gcd(b,r),这里两个数的大小是不会增大的,那么我们也就得到了关于两个数的最大公约数的一个递归求法。

int gcd(int a, int b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}

递归至 b==0(即上一步的 a%b==0) 的情况再返回值即可。

上述算法被称作欧几里得算法(Euclidean algorithm)。

欧几里得算法的时间效率如何呢?下面我们证明,欧几里得算法的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

当我们求 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) 的时候,会遇到两种情况:

  • a < b a < b a<b,这时候 gcd ⁡ ( a , b ) = gcd ⁡ ( b , a ) \gcd(a,b)=\gcd(b,a) gcd(a,b)=gcd(b,a)
  • a ≥ b a \geq b ab,这时候 gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   b ) \gcd(a,b)=\gcd(b,a \bmod b) gcd(a,b)=gcd(b,amodb),而对 a a a 取模会让 a a a 至少折半。这意味着这一过程最多发生 O ( log ⁡ n ) O(\log n) O(logn) 次。

第一种情况发生后一定会发生第二种情况,因此第一种情况的发生次数一定 不多于 第二种情况的发生次数。

从而我们最多递归 O ( log ⁡ n ) O(\log n) O(logn) 次就可以得出结果。


多个数的最大公约数

那怎么求多个数的最大公约数呢?显然答案一定是每个数的约数,那么也一定是每相邻两个数的约数。我们采用归纳法,可以证明,每次取出两个数求出答案后再放回去,不会对所需要的答案造成影响。


扩展欧几里得算法

扩展欧几里得算法(Extended Euclidean algorithm, EXGCD),常用于求 a x + b y = gcd ⁡ ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b) 的一组可行解。

  • 证明

    a x 1 + b y 1 = gcd ⁡ ( a , b ) ax_1+by_1=\gcd(a,b) ax1+by1=gcd(a,b)
    b x 2 + ( a   m o d   b ) y 2 = gcd ⁡ ( b , a   m o d   b ) bx_2+(a\bmod b)y_2=\gcd(b,a\bmod b) bx2+(amodb)y2=gcd(b,amodb)
    由欧几里得定理可知: gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   b ) \gcd(a,b)=\gcd(b,a\bmod b) gcd(a,b)=gcd(b,amodb)
    所以 a x 1 + b y 1 = b x 2 + ( a   m o d   b ) y 2 ax_1+by_1=bx_2+(a\bmod b)y_2 ax1+by1=bx2+(amodb)y2
    又因为 a   m o d   b = a − ( ⌊ a b ⌋ × b ) a\bmod b=a-(\lfloor\frac{a}{b}\rfloor\times b) amodb=a(ba×b)
    所以 a x 1 + b y 1 = b x 2 + ( a − ( ⌊ a b ⌋ × b ) ) y 2 ax_1+by_1=bx_2+(a-(\lfloor\frac{a}{b}\rfloor\times b))y_2 ax1+by1=bx2+(a(ba×b))y2
    a x 1 + b y 1 = a y 2 + b x 2 − ⌊ a b ⌋ × b y 2 = a y 2 + b ( x 2 − ⌊ a b ⌋ y 2 ) ax_1+by_1=ay_2+bx_2-\lfloor\frac{a}{b}\rfloor\times by_2=ay_2+b(x_2-\lfloor\frac{a}{b}\rfloor y_2) ax1+by1=ay2+bx2ba×by2=ay2+b(x2bay2)
    因为 a = a , b = b a=a,b=b a=a,b=b,所以 x 1 = y 2 , y 1 = x 2 − ⌊ a b ⌋ y 2 x_1=y_2,y_1=x_2-\lfloor\frac{a}{b}\rfloor y_2 x1=y2,y1=x2bay2
    x 2 , y 2 x_2,y_2 x2,y2 不断代入递归求解直至 gcd ⁡ \gcd gcd(最大公约数,下同)为 0 递归 x=1,y=0 回去求解。
// 求x, y,使得ax + by = gcd(a, b)
int extend_gcd(int a, int b, int &x, int &y){
    if (!b){
        x = 1; y = 0;
        return a;
    }
    int d = extend_gcd(b, a % b, y, x);
    y -= (a/b) * x;
    return d;
}

裴蜀定理

是一个关于最大公约数的定理。

其内容是:

a , b a,b a,b 是不全为零的整数,则存在整数 x , y x,y x,y, 使得 a x + b y = gcd ⁡ ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b).


进一步结论

设自然数 a、b 和整数 n。a 与 b 互素。考察不定方程:

a x + b y = n ax+by=n ax+by=n

其中 x 和 y 为自然数。如果方程有解,称 n 可以被 a、b 表示。

C = a b − a − b C=ab-a-b C=abab。由 a 与 b 互素,C 必然为奇数。则有结论:

对任意的整数 n,n 与 C − n C-n Cn 中有且仅有一个可以被表示。

即:可表示的数与不可表示的数在区间 [ 0 , C ] [0,C] [0,C] 对称(关于 C 的一半对称)。0 可被表示,C 不可被表示;负数不可被表示,大于 C 的数可被表示。


几何意义

重新观察方程 a x + b y = n ax+by=n ax+by=n,将它看成一条直线。直线与两坐标轴在第一象限围成三角形。

n < a b n<ab n<ab 的时候,这个直线在第一象限,至多只能通过一个整点。

根据上述讨论:当 n 可以被表示的时候,直线恰好经过一个整点;当 n 不可以被表示的时候,直线不经过整点(在第一象限)。

这结论也可以理解为:作三角形(0,0)(b,0)(0,a)。随着 n 从 0 不断增加,直线向右上方平移,整点会一个一个地通过直线,直到最后才撞上两个整点。

因此,小于等于 n 的能被表示的非负整数的数量,恰好就是直线 a x + b y = n ax+by=n ax+by=n(含)与两坐标轴(含)在第一象限围成三角形覆盖的整点个数。


另一种解释

考虑模 b 意义下每个剩余系中最小能被表示的值是多少——大于他们的可以通过增加若干个 b 得到。

观察原方程,a 的若干倍数 0 , a , ⋅ ⋅ ⋅ , ( b − 1 ) a 0, a,···, (b−1)a 0,a,,(b1)a ( m o d b ) \pmod b (modb) 意义下互不相同。这些数恰好是这些最小值。那么当 n < a b n<ab n<ab 时,小于等于 n 的能被表示的非负整数的数量是:

∑ i = 0 [ n a ] [ n − i a b ] \sum\limits_{i=0}^{\left[\frac{n}{a}\right]}\left[\frac{n − ia}{b}\right] i=0[an][bnia]

这是一个非常经典的直线下整点问题,恰好是这条直线:

y = − a b x + n b y=-\frac{a}{b}x+\frac{n}{b} y=bax+bn

a x + b y = n ax+by=n ax+by=n

使用类欧几里得算法可以在 O ( log ⁡ max ⁡ ( a , b ) ) O(\log \max(a,b)) O(logmax(a,b)) 的时间内求解。因此我们得到了计算小于等于 n 的能被表示的非负整数的数量的工具。

n个整数间的裴蜀定理

a 1 , a 2 , a 3 ⋯ a n a1,a2,a3\cdots an a1,a2,a3an n n n个整数,d是它们的最大公约数,那么存在整数 x 1 ⋯ x n x1\cdots xn x1xn使得 x 1 ∗ a 1 + x 2 ∗ a 2 + ⋯ x n ∗ a n = d x1*a1+x2*a2+\cdots xn*an=d x1a1+x2a2+xnan=d
特别来说,如果 a 1... a n a1...an a1...an存在任意两个数是互质的(不必满足两两互质),那么存在整数 x 1 ⋯ x n x1\cdots xn x1xn使得 x 1 ∗ a 1 + x 2 ∗ a 2 + ⋯ x n ∗ a n = 1 x1*a1+x2*a2+\cdots xn*an=1 x1a1+x2a2+xnan=1。证法类似两个数的情况。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值