兩個數的最大公約數 GCD
整數 a 和 b 的最大公約數記爲 gcd a , b)
1.輾轉相除法
- 遞歸版
int GCD(int a,int b)
{
return b == 0 ? a : GCD(b , a % b);
}
短小精悍
- 非遞歸版
int GCD(int a,int b)
{
while(b != 0)
{
int n = a % b;
a = b;
b = n;
}
return a;
}
時間複雜度差不多是O(log2n),非常快了
2.內置函數
- 先引入頭文件 #include<algorithm>
std::__gcd(a,b);
- 內部實現
template<typename EuclideanRingElement>
EuclideanRingElement __gcd(EuclideanRingElement m, EuclideanRingElement n)
{
while (n != 0)
{
EuclideanRingElement t = m % n;
m = n;
n = t;
}
return m;
}
內置的算法跟上面的非遞歸版一樣!
兩個數的最小公倍數 LCM
整數 a 和 b 的最小公倍數記爲 lcm(a , b)
顯然有 gcd(a,b) 整除 lcm(a,b)
那麼可以知道 lcm(a,b) = a * b / gcd(a,b)
- 代碼
int LCM(int a,int b)
{
return a * b / gcd(a,b);
}
gcd(a,b)參考前面
多個數的最大公約數
求多個數的最大公約數,考慮到c++的泛型編程,就很容易實現。
具體實現思路爲倒着一個一個的求出第一個數的因數,依次拿其餘的數除以該因數,若所有的數都能除盡該因數,則該因數即爲所求的最大公因數。倒着求因數保證了"最大"。
- 泛型實現求最大公約數
template <typename RAIter>
int gcd_s(RAIter _begin, RAIter _end)
{
bool _isDivisible(true),_flag(false);
for(int i = *_begin;i>=2;--i){//倒着求_begin的因數
if(*_begin % i == 0){
_flag = true;
for(RAIter _next = _begin+1;_next!=_end;++_next){//依次判斷_begin的因數能不能整除其餘的數
if(*_next % i != 0){
_isDivisible = false;
break;
}
}
}
else
_flag = false;
if(_isDivisible && _flag)//若能整除其餘的所有數,則該因數即爲最大公因數
return i;
_isDivisible = true;
}
return 1;//所有因數都不滿足,說明1是最大公因數
}
由上面的分析不難看出,每次是求的第一個數的因數,那麼如果區間第一個數是所有數裏面最小的,那麼代碼運行速度肯定是最快的,所以使用前讓區間第一個數字儘量的小。使用前可以用內置函數 sort()
排一下序
- 使用方法
vector<int> a{9,108,63,57,12};
array<int,5> b{9,108,63,57,12};
int c[5]{9,108,63,57,12};
cout<< gcd_s(a.begin(),a.end()) <<endl;
cout<< gcd_s(b.begin(),b.end()) <<endl;
cout<< gcd_s(c,c+5) <<endl;//普通數組調法[數組名,數組名+長度)
cout<< gcd_s(begin(c),end(c)) <<endl;//普通數組也可以這樣調
多個數的最小公倍數
考慮兩個數的最小公倍數求法,自然想到將所有數乘起來除以最大公約數。但是很遺憾這樣並不可行,例如9,10,5的最大公約數爲1,而最大公倍數爲90 ≠ 9 × 10 × 5 ÷ 1
但是基於這個思路我們可以想到先求出前兩個數的最小公倍數,這樣問題規模就從n變爲n-1,重複這個步驟即可得到最終答案。
- 泛型求最小公倍數
template <typename RAIter>
int lcm_s(RAIter _begin,RAIter _end)
{
int result = *_begin * *(_begin+1) / __gcd(*_begin,*(_begin+1));
for(RAIter _next = _begin+2;_next!=_end;++_next)
result = result * (*_next) / __gcd(result,*_next);
return result;
}
調用方法與上面的泛型最大公約數一樣。