【拾遗补阙】更相减损术&&辗转相除法(gcd)

【拾遗补阙】更相减损术&&辗转相除法

更相减损术

  1. 原理推导

    • 设两个正整数为a、ba > b,根据辗转相除法的原理,a和b的最大公因数等于b和a - b的最大公因数。更相减损术就是基于这个原理,不断地用较大数减去较小数来逐步缩小两个数的范围,直到两个数相等,此时这个数就是最大公因数。
  2. 算法步骤

    • 例如,求98和63的最大公因数。
      • 第一步:因为98>63,所以98 - 63 = 35
      • 第二步:此时63>35,则63 - 35 = 28
      • 第三步:35>28,35 - 28 = 7
      • 第四步:28>7,28 - 7 = 21
      • 第五步:21>7,21 - 7 = 14
      • 第六步:14>7,14 - 7 = 7
      • 此时两个数相等,所以98和63的最大公因数是7
  3. 代码实现(以C++为例)

    • int gcd(int a, int b) {
          while (a!= b) {
              if (a > b) {
                  a = a - b;
              } else {
                  b = b - a;
              }
          }
          return a;
      }
      
    • 这段代码定义了一个函数gcd,它接受两个整数ab作为参数。在函数内部,通过一个while循环不断比较ab的值。如果ab不相等,就根据它们的大小关系用较大数减去较小数。当ab相等时,循环结束,此时返回的a(或b,因为它们相等)就是原来两个数的最大公因数。

辗转相除法

  1. 原理推导
    • 设两个正整数为 a、b,a > b,辗转相除法基于这样一个原理:a\和 b的最大公因数等于 b和 a除以b的余数。通过不断地用除数作为新的被除数,余数作为新的除数进行相除操作,直到余数为 0,此时的除数就是原来两个数的最大公因数。
  2. 算法步骤
    • 例如,求 252 和 105 的最大公因数。
      • 第一步:用 252除以105,商 = 2,余数= 42
      • 第二步:把 105 作为新的被除数,42作为新的除数,得到新余数21
      • 第三步:再把 42作为被除数,21 作为除数,此时余数为 0
      • 所以 252和 105 的最大公因数就是最后的除数21
  3. 代码实现(以 C++为例)
    • int gcd(int a, int b) {
          if(b>a) swap(a,b);
          while (b != 0) {
              int temp = a % b;
              a = b;
              b = temp;
          }
          return a;
      }
      
    • 这段代码定义了一个函数 gcd,它接受两个整数 ab 作为参数。在函数内部,通过一个 while 循环,只要除数 b 不为 (0),就先计算 (a) 除以 (b) 的余数 temp,然后把除数 b 的值赋给被除数 a,把余数 temp 的值赋给除数 b,继续下一轮的计算。当 b 为 (0) 时,循环结束,此时返回的 a 就是原来两个数的最大公因数。

    • 原理补充解释:
      • 从更相减损术开始解释,假设a,b(a>b)的gcd(最大公因数)是x,则a=nx,b=mx,a-b=(n-m)x,所以a-b也可以被x整除;
      • 例如,求98和63的最大公因数。
    • 第一步:因为98>63,所以98 - 63 = 35,即14*7-9*7=5*7
    • 第二步:此时63>35,则63 - 35 = 28,即9*7-5*7=4*7
    • 第三步:35>28,35 - 28 = 7,即5*7-4*7=1*7
    • 第四步:28>7,28 - 7 = 21,即4*7-1*7=3*7
    • 第五步:21>7,21 - 7 = 14,即3*7-1*7=2*7
    • 第六步:14>7,14 - 7 = 7,即2*7-1*7=1*7
    • 此时两个数相等,所以98和63的最大公因数是7
      • 咱们可以发现在不断的操作下,最后a,b都会等于1倍的gcd
    • 极简更相减损术:
int gcd(int a, int b)
{
    if (a < b) swap(a, b);
    return (a == b) ? a : gcd(a - b, b);
}

  • 对于上面的过程咱们可以发现对于同一个因子(1*7)减去了许多次,那么是否可以简化这一块的部分呢?
  • 那也就是辗转相除法做到的事:a%b一定小于b,省去更相减损术中的判断和部分减去操作
  • 极简辗转相除法:
int gcd(int a, int b)
{
    return 0 == b ? a : gcd(b, a % b);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值