多個數的最大公約數


---恢復內容開始---

最近在看一本算法的書。講的都是一些基本的問題,並沒有涉及很復雜的算法,或者說這本書更看重技巧。

其中開篇就講了最大公約數的算法,覺得有可取之處,和大家分享一下。

提到最大公約數我們最先想到的一定是輾轉相除法。

沒錯,永遠不要蔑視我們的祖先,他們的智慧是無窮的。(扯遠了,嘿嘿)

我們都在用輾轉相除法來求最大公約數,卻很少去想為什么輾轉相除法就能求最大公約數呢?或者說怎么證明算法的正確性呢(至少我之前完全沒有想過)。

這里我們感性的認識一下輾轉相除法(不是很嚴格地證明一下)。

假設兩個數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;
         }
      }
    }
}

 

 

---恢復內容結束---


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM