家喻户晓的数学小技巧——欧几里得算法

本文深入探讨了求解两数最大公因数的各种方法,包括暴力枚举、更相减损术及其优化——欧几里得算法。通过实例演示算法步骤,并分析了每种方法的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景1

  • 给定两个数xxxyyy
  • 求出这两个数的最大公因数。

暴力1

  • 直接从1到min(x,y)min(x,y)min(x,y)枚举,找出最大的能分别整除它们两个的数即可。
  • 时间复杂度:O(min(x,y))O(min(x,y))O(min(x,y))

暴力2

  • 求出xxx的所有约数,再求出yyy的所有约数。
  • 从中查找出公共的数,在所有公共的数中找出最大值即可。
  • 时间复杂度O(max(x,y))O(\sqrt{max(x,y)})O(max(x,y))

引入——更相减损术

  • 更相减损术是出自《九章算术》的一种求最大公约数的算法,它原本是为约分而设计的,但它适用于任何需要求最大公约数的场合。
  • 原文:可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
  • 说人话:
    • 对于两个数,假如两个数都是偶数,先分别对每一个数除2,直到至少有一个数变成奇数为止。
    • 若这两个数相同,那么最大公约数就是这个数乘上2n2^n2nnnn是刚才除2的次数。
    • 否则,设这两个数分别为x,yx,yx,y,不妨设x<yx<yx<y,则新的x′=y−xx'=y-xx=yx,y′=xy'=xy=x。再重新判断是否相等。
  • 举例子:
    • 对于606060100100100,求出它们的最大公约数。
    • 首先不断除2,最终得到151515252525
    • 发现15≠2515 \neq 2515=25,所以151515变成25−15=1025-15=102515=10252525变成151515
    • 发现10≠1510 \neq 1510=15,所以101010变成15−10=515-10=51510=5151515变成101010
    • 发现5≠105 \neq 105=10,所以101010变成10−5=510-5=5105=5555变成555
    • 这时5=55 = 55=5,所以最大公约数就是5∗22=205*2^2=20522=20
  • 其实我们发现,之前不用除2也一样可以求出最大公约数
  • 正确性的证明
    • 假若aaax,yx,yx,y的公因数,x<yx<yx<y。则aaa一定也是y−x,xy-x,xyx,x的公因数。
    • 这时十分显然的,设y=a∗y0,x=a∗x0y=a*y0,x=a*x0y=ay0,x=ax0,则y−x=a∗(y0−x0)y-x=a*(y0-x0)yx=a(y0x0)aaa也是其因数。
    • 反过来也是一样的,若aaay−x,xy-x,xyx,x的公因数,x<yx<yx<y。则aaa一定也是x,yx,yx,y的公因数。
    • 所以y−x,xy-x,xyx,x的公因数与x,yx,yx,y的公因数是等价的。
    • 对于两个相同的数,它们的最大公因数显然是它们本身,有这个边界条件往上推即可得到原本两个数的最大公因数。
  • 但是,假若xxx特别小,yyy特别大,时间复杂度就会退化到O(y)O(y)O(y),没能完全优化时间复杂度。
  • 不过,它给我们提供了一个非常好的思想:

欧几里得算法

  • 我们发现,重复的减法其实相当于取模的过程,所以我们直接取模就好了。
  • x,y(x<y)x,y(x<y)x,y(x<y)推到ymod  x,xy\mod x,xymodx,x
  • 发现这两组数的最大公因数也是等价的。
  • 但注意此时的边界条件变为其中一个数为0,则最大公因数为另一个数。
  • 时间复杂度:
    • x>y2x>\frac{y}{2}x>2y,则ymod  x<y2y\mod x<\frac{y}{2}ymodx<2y
    • x<=y2x<=\frac{y}{2}x<=2y,则ymod  x<x<=y2y\mod x<x<=\frac{y}{2}ymodx<x<=2y
    • 即每一次,较大的那个数都会缩减至少一半。
    • 所以极限的时间复杂度是O(log2(max(x,y)))O(log_2(max(x,y)))O(log2(max(x,y)))的。

代码实现

int gcd(int x,int y){
	if(x==0) return y;
	else return gcd(y%x,x);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值