gcd詳解


簡述

  給你兩個數a和b,要求求出a和b的最大公約數。為了解決這個問題,我們可以想到很多方法,窮舉法,輾轉相除法,更相減損法等。這里我們詳解介紹窮舉法和輾轉相除法。

問題描述

  我們把問題用數學語言進行描述:已知整數a和b,求一數k滿足a%k==0&&b%k==0,且k要盡可能大。

窮舉法

  因為k小於等於a和b,所以我們可以從a和b選一個數開始進行窮舉,這里我們選擇較小的那個數,因為k一定小於等於較小那個數。

int gcd(int a,int b){
    int num=min(a,b);
    for(int i=num;i>=1;i--){
        if(a%i==0&&b%i==0) 
            return i;
    }
}

  這個算法的時間復雜度為O(min(a,b)),因為最多會執行min(a,b)次,當a和b特別大的時候,這個程序是很慢的。

輾轉相除法

  輾轉相除法又稱歐幾里得算法,這是我們小學就學過的算法,古希臘數學家歐幾里德在其著作《The Elements》中最早描述了這種算法,所以被命名為歐幾里德算法,又在九章算術里描述為輾轉相除法。

  我們現在將求a和b兩個數的最大公約數定義為函數gcd(a,b)。

  輾轉相除法的算法思想是,gcd(a,b)=gcd(b,a%b),當b為0時gcd(a,b)為a。不斷重復gcd(a,b)=gcd(b,a%b)則b終會等於0,最后求出等式的結果。

  例如我們現在要求gcd(9,12),則可以寫出以下的過程:

  gcd(9,12)=gcd(12,9%12)=gcd(12,9)=gcd(9,12%9)=gcd(9,3)=gcd(3,9%3)=gcd(3,0)=3

int gcd(int a,int b){
    if(b==0) return a;
    return gcd(b,a%b);
}

  輾轉相除法的時間復雜度為O(logn),證明省略。

輾轉相除法的證明

  為什么gcd(a,b)=gcd(b,a%b)呢?

  我們設gcd(a,b)=k,r=a%b。

  可得a=sk,b=tk,s和t互質,a=bq+r,q為正整數

  左帶入右得sk=tkq+r,整理得r=k(s,tq),所以k也是r的因子。

  我們可以將求gcd(a,b)的過程理解為求a和b兩個因數集合里最大的相同數,將gcd(a,b)=gcd(b,a%b)過程可以理解為使用一個r代替b,使得b變小但r的因數集里包含最大公約數k,一直減小到0時,當時的a就是我們求的k了。

  我們開看一張gif圖,兩條線段的長度分別代表a和b,里面的一小段代表最大公約數,現在演示如何用輾轉相除法求最大公約數。

  

 

 

 

 

 

  


免責聲明!

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



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