day54 求两个数的最大公约数(C++)

211 阅读3分钟

题目描述:

  • 描述: 求两个数的最大公约数

思路

  • 求整数a、b的最大公约数,顾名思义,其实就是求同时满足a%c=0、b%c=0的最大正整数c,即求能够同时整除a和b的最大正整数c。
  • 思路1:
    • 若a、b均不为0,则依次遍历不大于a(或b)的所有正整数,依次试验它是否同时满足a%c=0 、b% c = 0两式,并在所有满足两式的正整数中挑选最大的那个即是所求;
    • 若a、b其中有一个为0,那么最大公约数即为a、b中非零的那个;
    • 若a、b均为0,则最大公约数不存在(任意数均可同时整除它们)。
  • 评价:思路1该解法在大部分情况下要遍历不大于a(或b)的所有正整数,并依次测试它们是否满足条件,当a和b数值较大时(如10000000)该算法的时间复杂度较高,耗费的时间较多,往往不能在指定时间内得到结果
  • 思路2: 欧几里得算法
    • 若整数g为a、b(不同时为0)的公约数,则g满足:a=g*l,b=g*m(其中l、m为整数),同时a又可由b表示为:a=b*k+r(其中k为整数,r为a除以b后的余数)
    • 对如上三式做如下变形:g*l=g*m*k+r ==> r=g*(l-m*k) (g≠0)
    • 由上式可知,a、b的公约数g可以整除a除以b剩余的余数r(记为a mod b),即,a、b的公约数g同时也必是b、a mod b的公约数(因为满足既可以整除b又可以整除a mod b)
    • 疑问:若g是a、b的最大公约数,它同样也是b、a mod b的最大公约数吗?
    • 假设g是a、b的最大公约数,但它并不是b、amodb的最大公约数,即存在g'>g且g'同时整除b与a mod b,这样必存在整数I'与m'使下式成立:
      • b=gm;r=aModb=gl;b=g'*m';r = a Mod b = g'*l';
    • 同时a、b、r之间满足下式:
      • a=bk+r;a=gmk+gl;a=g(mk+g);(g0)a=b*k+r;a=g'*m'*k+g'*l';a=g'*(m'*k+g'*');(g'≠0)
    • 如上式,g'同时也整除a与b,那么g'同时也是a、b的公约数
    • 但b的最大公约数为g,而g'>g与假设不符,所以可证明a、b的最大公约数同时也是b、a mod b的最大公约数。
    • 这样,我们把求a、b的最大公约数转换成了求b、amodb的最大公约数,那么问题不变而数据规模则明显变小,我们可以不断重复该过程,直到问题缩小成求某个非零数与零的最大公约数,该非零数即是所求。

具体实现:

#include <iostream>
using namespace std;
/*
 思路:(若 a、b 全为0则它们的最大公约数不存在,此处a、b不会同时为0)若 a、b 其中之一为0,则它们的最大公约数为 a、b 中非0的那个; a、b 都不为0,则使新 a = b,新 b = a % b ,然后重复该过程。
 这就是欧几里得算法。
 */
int main(int argc, const char * argv[]) {
    int dividend_1=0;
    int dividend_2=0;
    int temp=0;         // 临时变量保存dividend1
    while (cin>>dividend_1>>dividend_2) {    
        while (dividend_2>0) {        // dividend_2不为0时一直更新
            temp=dividend_1;
            dividend_1=dividend_2;
            dividend_2=temp%dividend_2;
        }
        cout<<dividend_1<<endl;    // dividend_2为0时dividend_1即是所求
    }
    return 0;
}

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 28 天,点击查看活动详情