zoukankan      html  css  js  c++  java
  • C语言复习---获取最大公约数(辗转相除法和更相减损法)

    源自:百度百科 

    辗转相除法

    辗转相除法:辗转相除法是求两个自然数的最大公约数的一种方法,也叫欧几里德算法

    例如,求(319377):
    ∵ 319÷377=0(余319)
    ∴(319377)=(377319);
    ∵ 377÷319=1(余58)
    ∴(377319)=(31958);
    ∵ 319÷58=5(余29)
    ∴ (31958)=(5829);
    ∵ 58÷29=2(余0)
    ∴ (5829)= 29;
    ∴ (319377)=29

    用辗转相除法求几个数的最大公约数,可以先求出其中任意两个数的最大公约数,再求这个最大公约数与第三个数的最大公约数,依次求下去,直到最后一个数为止。最后所得的那个最大公约数,就是所有这些数的最大公约数。

    更相减损法

    第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
    第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
    则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。
    其中所说的“等数”,就是最大公约数。求“等数”的办法是“更相减损”法。所以更相减损法也叫等值算法。
    例1.用更相减损术求98与63的最大公约数。
    解:由于63不是偶数,把98和63以大数减小数,并辗转相减:
    98-63=35
    63-35=28
    35-28=7
    28-7=21
    21-7=14
    14-7=7
    所以,98和63的最大公约数等于7。
    这个过程可以简单的写为:
    (9863)=(3563)=(3528)=(728)=(721)=(714)=(77)=7.
    例2.用更相减损术求260和104的最大公约数。
    解:由于260和104均为偶数,首先用2约简得到130和52,再用2约简得到65和26。
    此时65是奇数而26不是奇数,故把65和26辗转相减:
    65-26=39
    39-26=13
    26-13=13
    所以,260与104的最大公约数等于13乘以第一步中约掉的两个2,即13*2*2=52。
    这个过程可以简单地写为:
    (260,104)(/2/2) =>(65,26)=(39,26)=(13,26)=(13,13)=13. (*2*2) => 52 [1]

    比较:

    比较辗转相除法与更相减损术的区别
    (1)都是求最大公因数的方法,计算上辗转相除法以除法为主,更相减损术以减法为主,计算次数上辗转相除法计算次数相对较少,特别当两个数字大小区别较大时计算次数的区别较明显。
    (2)从结果体现形式来看,辗转相除法体现结果是以相除余数为0则得到,而更相减损术则以减数与差相等而得到

    代码实现

    一:最简单方法

    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
        int m, n,temp,i;
        scanf("%d", &m);
        scanf("%d", &n);
        
        if (m>n)
        {
            temp = m;
            m = n;
            n = temp;
        }
    
        for (i = m; i >= 1;i--)
            if (m%i==0 && n%i==0)
                break;
    
        printf("%d
    ", i);
    
        system("pause");
        return 0;
    }

    二:辗转相除法(递归)

    #include <stdio.h>
    #include <stdlib.h>
    
    int gcd(int a, int b)
    {
        int mod;
        if ((mod = a % b) == 0)
            return b;
        return gcd(b, mod);
    }
    
    int main()
    {
        int m, n,ret;
        scanf("%d", &m);
        scanf("%d", &n);
    
        ret = gcd(m, n);
        printf("%d", ret);
        
        system("pause");
        return 0;
    }

    三:辗转相除法(非递归)

    int gcd(int a, int b)
    {
        int mod=a % b;
        while (mod!=0)
        {
            a = b;
            b = mod;
            mod = a % b;
        }
        return b;
    }

    四:更相减损法(非递归)

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int gcd(int a, int b)
    {
        int val= a - b;
        while (val != b)
        {
            if (b>val)
            {
                a = b;
                b = val;
            }
            else
            {
                a = val;
            }
            val = a - b;
        }
        return val;
    }
    
    int main()
    {
        int m, n,ret,temp,count=0;
        scanf("%d", &m);
        scanf("%d", &n);
    
        if (m == n)
        {
            printf("%d", m);
            return 0;
        }
    
        if (m < n)
        {
            temp = m;
            m = n;
            n = temp;
        }
    
        while (m%2 == 0 && n%2 == 0)
        {
            count++;
            m /= 2;
            n /= 2;
        }
        
        ret = gcd(m, n);
        printf("%d", ret*((int)pow(2,count)));  //使用pow需要进行(int)转换,不然会报错
        
        system("pause");
        return 0;
    }
     
     
     
     
  • 相关阅读:
    C风格字符串大写转小写
    指针的引用在函数中的应用
    Debug和Release区别
    差分约束系统(System Of Difference Constraints)
    poj_2299UltraQuickSort && poj_1804Brainman
    计算几何基础——矢量和叉积
    推荐ALGORITHM专题
    后缀数组之倍增法
    静态邻接表的简单实现
    归并排序&&树状数组求逆序数
  • 原文地址:https://www.cnblogs.com/ssyfj/p/9376945.html
Copyright © 2011-2022 走看看