求两个数的最大公约数,辗转相除法与更相减损法(递归迭代)

问题:给出两个数a和b,求出他们的最大公约数(greatest common divisor)。

解法一:辗转相除法,又叫欧几里得算法。两个正整数a和b(a>b),他们的最大公约数等于a除以b的余数和b之间的最大公约数。

比如10和25,25除以10余5,那么10和25的最大公约数等同于5和10之间的最大公约数。

//辗转相除法    递归解法
int gcd(int a,int b){
    if(a%b==0)
        return b;
    return (b,a%b);
}
//辗转相除法   迭代解法int gcd2(int a,int b){
    int t;
    while(b!=0){
        t=b;
        b=a%b;
        a=t;
    }
    return a;
} 

解法二:更相减损术,出自中国古代的《九章算术》。两个正整数a和b(a>b),他们的最大公约数等于a-b的差值c和较小数b的最大公约数。

比如10和25,25-10=15,那么10和25的最大公约数等于10和15的最大公约数。

//更相减损术  递归
int gcd3(int a,int b){
    if(a==b)
        return a;
    if(a>b)
        return gcd(a-b,b);
    else
        return gcd(b-a,a);
}
//更相减损术  迭代
int gcd4(int a,int b){
    while(a*b!=0){
        if(a>b)
            a=a-b;
        else
            b=b-a;
    }
    return a?a:b;
}

改进:更相减损术是不稳定的算法,当两个数相差悬殊时,如10000和1的最大公约数,要递归9999次。

做法;

当a和b都是偶数时,gcd(a,b)=2*gcd(a/2,b/2)=2*gcd(a>>1,b>>1)。

当a是奇数,b是偶数时,gcd(a,b)=gcd(a,b/2)=gcd(a,b>>1)。

当a是偶数,b是奇数时,gcd(a,b)=gcd(a/2,b)=gcd(a>>1,b)。

当a和b都是奇数数时,gcd(a,b)=gcd(a-b,b)。

//改进版:
int gcd5(int a,int b){
    if(a==b)
        return a;
    else if(a<b)
        return gcd5(b,a);    //始终让 a>b
    else{
        if(!(a&1)&&!(b&1)){    //两数都为偶数
            return gcd5(a>>1,b>>1)<<1;
        }else if((a&1)&&!(b&1)){    //a奇数 b偶数
            return gcd5(a,b>>1);
        }else if(!(a&1)&&(b&1)){    //a偶数 b奇数
            return gcd5(a>>1,b);
        }else
            return gcd(a,a-b);        //都是奇数 相减 

    }
}

算法复杂度:

辗转相除法:O(log(max(a,b)))

更相减损法:O(max(a,b))

改进更相减损法:O(log(max(a,b)))

原文地址:https://www.cnblogs.com/hekuiFlye/p/9379276.html

时间: 2024-10-10 12:31:43

求两个数的最大公约数,辗转相除法与更相减损法(递归迭代)的相关文章

C语言复习---获取最大公约数(辗转相除法和更相减损法)

源自:百度百科 辗转相除法 辗转相除法:辗转相除法是求两个自然数的最大公约数的一种方法,也叫欧几里德算法. 例如,求(319,377): ∵ 319÷377=0(余319) ∴(319,377)=(377,319): ∵ 377÷319=1(余58) ∴(377,319)=(319,58): ∵ 319÷58=5(余29) ∴ (319,58)=(58,29): ∵ 58÷29=2(余0) ∴ (58,29)= 29: ∴ (319,377)=29. 用辗转相除法求几个数的最大公约数,可以先求出

【C语言】最大公约数(更相减损法)和(辗转相除法)

#include<stdio.h> #include <math.h> /* 编写一个函数,传入a,b两个int类型的变量,返回两个值的最大公约数. 例如:输入传入(0 , 5)函数返回5,传入(10 , 9)函数返回1,传入(12 , 4)函数返回4 */ //更相减损法 int fuc(int m,int n) { int i=0,temp,x; while(m%2==0 && n%2==0) //判断m和n能被多少个2整除 { m/=2; n/=2; i+=1

写一个方法,求两个数的最大公约数和最小公倍数。

package homework0702; /* * 最大公约数 利用辗转相除法求解两个正整数的最大公约数 在循环中,只要除数不等于0,用较大的数除以较小的数,将小的一个数作为下一轮循环的大数,取得的余数作为下一轮循环较小的数,如此循环直到较小的数值为0,返回较大的数.即为最大公约数. 辗转相除法(欧几里得算法) 定理:两个整数的最大公约数等于其中较小的那个数和两数的相除余数的最大公约数.最大公约数(greatest common divisor)缩写为gcd. 最小公倍数 最小公倍数 = (a

求两个数的最大公约数

求两个数的最大公约数 问题:给定两个正整数a和b,求他们的最大公约数. 最简单的方法就是穷举法,如果a>b,那么依次计算1~b的所有整数是否是a和b的公约数. public static void main(String[] args) { long timer = System.currentTimeMillis(); System.out.println(getGCB(1000234234,1242342390)); System.out.println(System.currentTime

C语言求两个数中最大公约数

在C语言中如何求两个数的最大公约数呢?下面用三种方法进行求解. 方法一:穷举法. 先比较两个数的大小,然后找出较小数t,最后判断t为何值时两个数都能整除,此方法效率较低. 代码如下: #include<stdio.h> int main() {      int num1,num2,temp,i;      scanf("%d%d",&num1,&num2);      if(num1>num2)      {            temp=num1

求两个数的最大公约数&amp;求N个数的最大公约数

一.求两个数的最大公约数 如何编程计算N个数的最大公约数(Greatest common divisor)呢?第一想法那便是两两计算,但是往往最简单的想法是不怎么靠谱的.下面用递归来解决.递归有一大好处,那便是递归非常符合人的思维,有时即使很复杂,但是依仗着递归的规律性,可以断定或推测出按递归做是正确的.如果说递归的性能低,我们可以采用备忘录法,用表记录过已经计算过的问题,避免二次计算,这样在一定程度上可以带来性能上的提升.我们可以先用递归实现,倘若在实际情况中发现性能问题,我们可以再进行优化.

求两个数的最大公约数和最小公倍数

import java.util.Scanner; //求两个数的最大公约数,最小共倍数. public class CommonMaxDivisor { public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int m=scanner.nextInt(); int n=scanner.nextInt(); scanner.close(); CommonMaxDivisor cmd=new

求两个数的最大公约数和最小公倍数 C语言

C程序设计第八章的第一道题目,求两个数的最大公约数和最小公倍数.需要注意一下几点: 1.最大公约数和最小公倍数间的关系: 设两个数是a,b最大公约数是p,最小公倍数是q 那么有这样的关系:ab=pq 所以q=ab/p.2.任意整数和0的公约数是该整数的所有约数,所以它们的最大公约数为该整数本身.3.碾转相除法:被除数%除数=余数,如果余数不为0,就让原来的除数做为被除数,余数作为除数,再进行运算 被除数%除数=余数,直到得到的余数为0为止,此时的除数就是最大公约数. #include <stdi

[000]求两个数的最大公约数

求出两个数的最大公约数 1 int foo(int v1, int v2) 2 { 3 while(v2) { 4 int temp = v2; 5 v2 = v1 % v2; 6 v1 = temp; 7 } 8 9 return v1; 10 } [000]求两个数的最大公约数,布布扣,bubuko.com