求最大公約數(輾轉相除法)

AC-fun發表於2019-06-03

最大公約數(Greatest Common Divisor)指兩個或多個整數共有約數中最大的一個。

也稱最大公因數、最大公因子,a, b的最大公約數記為(a,b),同樣的,a,b,c的最大 公約數記為(a,b,c),多個 整數的最大公約數也有同樣的記號。求最大公約數有多種 方法,常見的有 質因數分解法、 短除法、 輾轉相除法、 更相減損法。與最大公約數相對應的概念是 最小公倍數,a,b的 最小公倍數記為[a,b]。

再來介紹一下輾轉相除法:

輾轉相除法又叫歐幾里得演算法,是歐幾里得最先提出來的.輾轉相除法的實現,是基於下面的原理(在這裡用(a,b)表示a和b的最大公因數):
  (a,b)=(a,ka+b),其中a、b、k都為自然數.………………①
  也就是說,兩個數的最大公約數,將其中一個數加到另一個數上,得到的新數,其公約數不變,比如(4,6)=(4+6,6)=(4,6+2×4)=2.要證明這個原理很容易:如果p是a和ka+b的公約數,p整除a,也能整除ka+b.那麼就必定要整除b,所以p又是a和b的公約數,從而證明他們的最大公約數也是相等的.
  基於上面的原理,就能實現我們的迭代相減法:
  (78,14)=(64,14)=(50,14)=(36,14)=(22,14)=(8,14)=(8,6)=(2,6)=(2,4)=(2,2)=(0,2)=2
  基本上思路就是大數減去小數,一直減到能算出來為止,在作為練習的時候,往往進行到某一步就已經可以看出得值.迭代相減法簡單,不過步數比較多,實際上我們可以看到,在上面的過程中,由(78,14)到(8,14)完全可以一步到位,因為(78,14)=(14×5+8,14)=(8,14),由此就誕生出我們的輾轉相除法.
  用輾轉相除法求(a,b).設r0=b,r1=a,反覆運用除法算式,得到一系列整數qi,ri和下面的方程:
  相當於每一步都運用原理①把數字進行縮小,上面右邊就是每一步對應的縮小結果,可以看出,最後的餘數rn就是a和b的公約數.迭代相減法和輾轉相除法在本質上是一樣的,相對來說,減法比較簡單(需要10步),但是除法步數少(僅需4步).

因此可以通過這個原理來求出最大公約數: 

#include<iostream>
#include<cstdio>
using namespace std;

int fun(int m,int n){
	int rem;			//餘數,當餘數為0的時候,最後的m即為最大公約數
	//先用較小的數對較大的數取餘,再用餘數對較小的數求餘,直到餘數為零 
	while(n > 0){
		rem = m % n;
		m = n;
		n = rem;
	}
	return m;			//將結果返回			
}
int main(){
	int n,m;
	cin>>m>>n;
	cout<<"m和n的最大公約數為:"<<fun(m,n)<<endl;
	return 0; 
} 

因為到餘數為零結束,所以還可以將程式簡化一下用遞迴來求:

int fun(int m,int n){
	if(n==0) return m;
	return fun(n,m%n);
}

再簡化一下,用一行程式碼來求:

int gcd(int m, int n) {
    return n ? gcd(n, m % n) : m;
}

 

相關文章