• 求最大公约数的几种常见的方法 【详解】


    目录

    一、关于公约数

    二、计算最大公约数的方法 

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

    2. 更相减损法(辗转相减法)

    3. 分解质因数法

    4. 穷举法 

    5. 递归法

    6. 短除法

    三、总结


    一、关于公约数

    首先 ,先介绍一下公约数:

    公约数(公因数),一个能被若干个整数同时整除的的整数,公约数中最大的称为最大公约数

    公约数与公倍数相反,就是既是A的约数同时也是B的约数的数,12和15的公约数有1,3,最大公约数就是3。再举个例子,30和40,它们的公约数有1,2,5,10,最大公约数是10。

    计算两个数组的最大公约数,例如计算 a,b两个数的最大公约数。

    二、计算最大公约数的方法 

    1. 辗转相除法(欧几里得算法

    第一步,先是两个数进行 模运算,来求余数   即 a%b

    ①当a可以被b整除时 (a%b == 0),直接返回 b , b就是最大公约数。例a = 4;b = 2;a%b==0,所以b = 2,就是这两个数的最大公约数。

    ②当a%b != 0时,则进行辗转交换,这里用第三个变量来接收 c = a%b; 用 a 来接收 b的值,用b来接收c(余数的值)。

    例 a = 6,b = 12; c = a%b = 6;    a = b = 12;  b = c = 6;  a%b = 12%6 = 0。 最大公因数为 6。

    共有约数中最大的一个

    ③重复上述①和② 

    算法流程图

    代码展示 

    1. //求最大公约数 辗转相除法
    2. #include
    3. int fun(int a,int b)
    4. {
    5. while (a % b != 0)
    6. {
    7. int c = a % b;
    8. a = b;
    9. b = c;
    10. }
    11. return b;
    12. }
    13. int main()
    14. {
    15. int a = 0;
    16. int b = 0;
    17. scanf("%d %d",&a,&b);
    18. int ret = fun(a,b);
    19. printf("最大公约数为:%d",ret);
    20. return 0;
    21. }

    示例:

    2. 更相减损法(辗转相减法)

    更相减损术是出自《九章算术》的一种求最大公约数的算法,它原本是为约分而设计的,但它适用于任何需要求最大公约数的场合。

    思想

    原文是

    可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。

    翻译:

    第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;

    若不是则执行第二步。

    第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。

    则第一步中约掉的若干个2的积与第二步中等数的乘积就是所求的最大公约数。

    其中所说的“等数”,就是公约数。求“等数”的办法是“更相减损”法。

    提取上述的一些思想

    例 a = 12, b = 18;  b = b - a = 18 - 12 = 6; a >b; a = a - b = 12 - 6 = 6; a = b = 6; 。

    算法流程图

    代码展示 

    1. //更相减损法(辗转相减法)
    2. #include
    3. int main()
    4. {
    5. int a = 0;
    6. int b = 0;
    7. scanf("%d %d",&a,&b);
    8. while (a != b)
    9. {
    10. if (a > b)
    11. a = a - b;
    12. else
    13. b = b - a;
    14. }
    15. printf("最大公约数是:%d",a);
    16. return 0;
    17. }

    示例

    3. 分解质因数法

     把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是这几个数的最大公约数

    例如:求24和60的最大公约数,先分解质因数,得24=2×2×2×3,60=2×2×3×5,24与60的全部公有的质因数是2、2、3,它们的积是2×2×3=12,所以,(24,60)= 12

    代码展示

    1. #include
    2. void fun(int * arr,int n)
    3. {
    4. int i = 2, j = 0;
    5. while (n > 1)
    6. {
    7. if (n % i == 0)
    8. {
    9. arr[j++] = i;
    10. n /= i;
    11. }
    12. else
    13. {
    14. i++;
    15. }
    16. }
    17. }
    18. int gcd(int a,int b)
    19. {
    20. //因为要进行找这个数的共有的因数,所以这里用数组来接收
    21. int arr_a[100] = {0};//放a的所有因数
    22. int arr_b[100] = {0};//放b的所有因数
    23. //进行放因数
    24. fun(arr_a,a);
    25. fun(arr_b,b);
    26. //找出公共的因数,然后相乘
    27. int i = 0, j = 0, ret = 1;
    28. while (arr_a[i] != 0 && arr_b[j] != 0)
    29. {
    30. if (arr_a[i] == arr_b[j])
    31. {
    32. ret *= arr_a[i];
    33. i++;
    34. j++;
    35. }
    36. else if (arr_a[i] > arr_b[j])
    37. {
    38. j++;
    39. }
    40. else
    41. {
    42. i++;
    43. }
    44. }
    45. return ret;
    46. }
    47. int main()
    48. {
    49. int a = 0;
    50. int b = 0;
    51. scanf("%d %d",&a,&b);
    52. int ret = gcd(a,b);//最大公因数
    53. printf("%d和%d的最大公因数是:%d",a,b,ret);
    54. return 0;
    55. }

     

    4. 穷举法 

     穷举法的基本思想是根据题目的部分条件确定答案的大致范围,并在此范围内对所有可能的情况逐一验证,直到全部情况验证完毕。若某个情况验证符合题目的全部条件,则为本问题的一个解;若全部情况验证后都不符合题目的全部条件,则本题无解。穷举法也称为枚举法

    这里的枚举法就是 先 用一个临时变量来接收(a或b) 其中的一个数,然后连个数进行模运算,两个数都模这个临时变量等于零就是最大公约数,否则临时变量每次减一,然后重复上述。

    代码展示 

    1. //穷举法
    2. #include
    3. int main()
    4. {
    5. int a = 0;
    6. int b = 0;
    7. scanf("%d %d",&a,&b);
    8. int t = a;
    9. while (t--)
    10. {
    11. if (a % t == 0 && b % t == 0)
    12. break;
    13. }
    14. printf("%d",t);
    15. return 0;
    16. }

    5. 递归法

    这里的递归法是基于辗转相除法的思想,然后通过递归来实现。

    两个数的最大公约数 ,其中 较小的数  和 两个数相除的余数 的最大公约数

    当 y / x%y == 0 时 , y就是最大公约数。

    不为0, 就递归 gcd(y,x%y),  gcd 下方代码有描述

    算法流程图

    代码实现 

    1. #include
    2. int gcd(int a, int b)
    3. {
    4. if (b == 0)
    5. return a;
    6. else
    7. return gcd(b,a%b);
    8. }
    9. int main()
    10. {
    11. int a = 0;
    12. int b = 0;
    13. scanf("%d %d", &a, &b);
    14. int ret = gcd(a,b);
    15. printf("%d",ret);
    16. return 0;
    17. }

    6. 短除法

    例如:求12与18的最大公因数。以下如有约数出现则为因数

    短除法例题:

    12的因数有:1、2、3、4、6、12。

    18的因数有:1、2、3、6、9、18。

    12与18的公因数有:1、2、3、6。

    12与18的最大公因数是6。

    算法思想:

    第一步:先是分别计算处两个数的所有因数,然后分别用数组来进行存放两个数组的所有因数(这里也可以只用一个数组)本例中为方便大家的理解采用两个数组进行存放。

    注意:这里的存放也是有技巧的,这里采取的是从大到小进行排序的(当然也可以进行采取从小到大进行排序)

    第二步:进行遍历找出相同的因数进行比较,使用一个临时变量用来存放最大公因数

     代码展示

    1. #include
    2. void fac(int* arr, int n)
    3. {
    4. int i = 0;
    5. int j = 0;
    6. int k = 0;
    7. for (i = 1; i <= n; i++)
    8. {
    9. if (n % i == 0)
    10. {
    11. arr[k++] = i;
    12. }
    13. }
    14. }
    15. int gcd(int a, int b)
    16. {
    17. int arr1[100] = { 0 };
    18. int arr2[100] = { 0 };
    19. fac(arr1, a);
    20. fac(arr2, b);
    21. //求同找最大
    22. int i = 0, j = 0, max = 1;
    23. while (arr1[i] != 0 && arr2[j] != 0)
    24. {
    25. if (arr1[i] == arr2[j])
    26. {
    27. if (max < arr1[i])
    28. {
    29. max = arr1[i];
    30. }
    31. i++;
    32. j++;
    33. }
    34. else if (arr1[i] < arr2[j])
    35. {
    36. i++;
    37. }
    38. else
    39. {
    40. j++;
    41. }
    42. }
    43. return max;
    44. }
    45. int main()
    46. {
    47. int a = 0;
    48. int b = 0;
    49. scanf("%d %d", &a, &b);
    50. int ret = gcd(a, b);
    51. printf("%d 和 %d 的最大公因数为 %d",a,b ,ret);
    52. return 0;
    53. }

    三、总结

    这里比较推荐是用 辗转相除法(欧几里得算法)和 《九章算术》中的 更相减损法

    多说一下,因为当时阿明浅浅学过遍辗转相除法,然后不久后就忘干净了,用的时候还要再去反复找,为了方便使用,干脆把 求解最大公约数 的几种常见的方法详细介绍一下,虽然不是最好,但是多少希望对大家有些帮助!

    希望大家对这些方法,有更加深刻的印象。

    加油!!! 

  • 相关阅读:
    从0到1构建界面设计系统思维
    Vue3响应式核心API 使用注意点
    .net core-利用BsonDocumentProjectionDefinition和Lookup进行 join 关联查询(MongoDB)
    LeetCode 2351. 第一个出现两次的字母
    thinkPHP项目搭建
    七、文件包含漏洞
    打表找规律与分析判断:ARC144C
    前端TS学习笔记 (JS和TS优劣对比)
    GBASE 8s基本命令:onstat -k讲解
    springMVC1之ModelAttribute注解
  • 原文地址:https://blog.csdn.net/qq_72505850/article/details/133902812