多个数的最大公约数

---恢复内容开始---

最近在看一本算法的书。讲的都是一些基本的问题,并没有涉及很复杂的算法,或者说这本书更看重技巧。

其中开篇就讲了最大公约数的算法,觉得有可取之处,和大家分享一下。

提到最大公约数我们最先想到的一定是辗转相除法。

没错,永远不要蔑视我们的祖先,他们的智慧是无穷的。(扯远了,嘿嘿)

我们都在用辗转相除法来求最大公约数,却很少去想为什么辗转相除法就能求最大公约数呢?或者说怎么证明算法的正确性呢(至少我之前完全没有想过)。

这里我们感性的认识一下辗转相除法(不是很严格地证明一下)。

假设两个数a,b且a>b。 设a除以b商k,余数为r,那么会有a=k*b+r,那么b和r的最大公约数,就是a和b的最大公约数。所以问题就转换求成除数和余数的最大公约数,依次递归,递归的出口就是一个已知的条件:如果a能够被b整除,那么b就是a和b的最大公约数,所以辗转相除法递归代码如下:

int GCD1(int num1,int num2)
{
   if(num1%num2==0)
   {
    return num2;
   }
   else
   {
    int next1=num2;
    int next2=num1%num2;
    return GCD1(next1,next2);
    }
}

还有一种我们耳熟能详的求最大公约数的算法就是更相减损术,他的基本思想就是:两个数a,b且a>b,那么令c=a-b,然后把 b和c看成新的a和b,递归下去,递归出口就是一个已知的条件:如果a=b,那么a和b的最大公约数就是a或b。其实更相减损术和辗转相除法是一个东东,更相减损术就是让辗转相除法中的商(k)恒为1,所以大多数情况下,辗转相除法的效率要比更相减损术的效率高。给出更相减损术的代码:

int GCD2(int num1,int num2)
{
   if(num1==num2)
   {
      return num2;
   }
   else
  {
      int next1=  (num1>num2)? (num1-num2):(num2-num1);
      int next2= (num1>num2)?num2:num1;
      if(next1>next2)
      {
       return GCD2(next1,next2);
      }
      else
      {
         return GCD2(next2,next1);
      }
    }
}

好了,步入这次的正题:多个数求最大公约数(实际上就是辗转相除法的扩展)给出算法:

设一组数a1,a2,a3,a4,a5..

(1)对这一组数进行排序(从大到小)

(2)对每两个相邻的两个数进行如下操作:

    设相邻的两个数为A和B(A在前,因为已经排序,所以A>B),如果A=n*B(n为整数),也就是A能够被B整除,那么就令A=B;如果A不能被B整除则令A=A%B。

(3)重复(1)、(2)知道数组中每个数都相等,则最大公约数就为这个数。

给出完整程序:

#include<iostream>
using namespace std;
void Sort(int* num,int n);
int GCD3(const int* num,int n);
int main()
{

  int num[4]={756,504,630,2226};
   int result=GCD3(num,4);
   cout<<"数组:";
   for(int i=0;i<4;i++)
   {
      cout<<num[i]<<"  ";
   }
   cout<<"的最大公约数为:"<<result<<endl;
   return 0;
}

int GCD3(const int* num,int n)
{
   int *temp=new int[n];
   for(int i=0;i<n;i++)
   {
      temp[i]=num[i];
   }
   do
   { 
      if(temp[0]==temp[n-1])
      {
         break;
      }
      else
      {
         Sort(temp,n);//排序
         for(int i=0;i<n-1;i++)
         {
            if(temp[i]%temp[i+1]==0)
            {
               temp[i]=temp[i+1];
            }
            else
            {
               temp[i]=temp[i]%temp[i+1];
            }
         }
      }
   }while(temp[0]!=temp[n-1]);
   return temp[0];
}

//排序
void Sort(int* num,int n)
{

  //冒泡排序法
   for(int i=0;i<n-1;i++)
   {
      for(int j=i;j<n-1;j++)
      {
         if(num[i]<num[j+1])
         {
            int temp=num[i];
            num[i]=num[j+1];
            num[j+1]=temp;
         }
      }
    }
}

---恢复内容结束---

时间: 2024-12-08 05:34:14

多个数的最大公约数的相关文章

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

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

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

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

【C语言】求两个数的最大公约数

思路: 辗转相除法:以小的数除大数,所得的是整数,那这个数就是最大公约数,不然就用余数来除刚才的除数,直到得到整数,这时作为除数的就是最大公约数. #include<stdio.h> int main() { int m,n,t,p; printf("请输入两个数:"); scanf("%d %d",&m,&n); if((m >= n) && (m % n==0)) { t=n; } if((p = m%n) &a

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

除了分解质因数,还有另一种适用于求几个较小数的最大公约数.最小公倍数的方法 下面是数学证明及算法实现 令[a1,a2,..,an] 表示a1,a2,..,an的最小公倍数,(a1,a2,..,an)表示a1,a2,..,an的最大公约数,其中a1,a2,..,an为非负整数.对于两个数a,b,有[a,b]=ab/(a,b),因此两个数最小公倍数可以用其最大公约数计算.但对于多个数,并没有[a1,a2,..,an]=M/(a1,a2,..,an)成立,M为a1,a2,..,an的乘积.例如:[2,

[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

一天一个算法:求俩个数的最大公约数和最小公倍数

求俩个数的最大公约数和最小公倍数 解答: 当较大数除以较小数余数等于0时,较小数为最大公约数. 两数相乘结果除以它们的最大公约数为最小公倍数. int cdivisor(int x1,int y1) { int r,temp; if (x1<y1) { temp =x1; x1 = y1; y1 = temp; } while(x1%y1)//当较大数除以较小数余数等于0时,较小数为最大公约数 { r=x1%y1; x1=y1; y1=r; } return y1; } int cmultipl

C语言辗转相除法求2个数的最小公约数

辗转相除法最大的用途就是用来求两个数的最大公约数. 用(a,b)来表示a和b的最大公约数. 有定理: 已知a,b,c为正整数,若a除以b余c,则(a,b)=(b,c). (证明过程请参考其它资料) 例:求 15750 与27216的最大公约数. 解: ∵27216=15750×1+11466 ∴(15750,27216)=(15750,11466) ∵15750=11466×1+4284 ∴(15750,11466)=(11466,4284) ∵11466=4284×2+2898 ∴(11466