最大公约数
(1)扩展欧几里德:
gcd(a,b)=gcd(b,a mod b)
证明:a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个公约数,则有
d|a, d|b,而r = a - kb,因此d|r
因此d是(b,a mod b)的公约数
假设d 是(b,a mod b)的公约数,则
d | b , d |r ,但是a = kb +r
因此d也是(a,b)的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证
(2)stein算法:
由J. Stein 1961年提出的Stein算法很好的解决了欧几里德算法中的这个缺陷,Stein算法只有整数的移位和加减法,为了说明Stein算法的正确性,首先必须注意到以下结论:
gcd(a,a)=a,也就是一个数和其自身的公约数仍是其自身。
当k与b互为质数,gcd(ka,b)=gcd(a,b),也就是约掉两个数中只有其中一个含有的因子不影响最大公约数。特殊地,当k=2时,说明计算一个偶数和一个奇数的最大公约数时,可以先将偶数除以2。(除以2即是向右移位1个);
#include <iostream> using namespace std; int gcd(int a, int b) //欧几里德 算法 { return b?gcd(b,a%b):a; } int stein_gcd(int a, int b) //stein 用位运算加速 { if(a == 0) return b; if(b == 0) return a; if(!(a&1) && !(b&1)) return stein_gcd(a>>1,b>>1)<<1; if(!(a&1)) return stein_gcd(a>>1,b); if(!(b&1)) return stein_gcd(a,b>>1); if(a < b) //利用位运算交换 { a = a^b; b = a^b; a = a^b; } return stein_gcd((a-b)>>1,b); //###########1 } int main() { int a,b; while(cin>>a>>b) { cout<<"Eucild: "<<gcd(a,b)<<endl; cout<<"Stein: "<<stein_gcd(a,b)<<endl; } }
对于上处#######1:
先看以下公式:
gcd(2*a,b) = gcd(a,b);
gcd(a,b) = gcd(a/2,b);
我们设a,b的最大公约数为d;a = xd,b = yd; 倒着推:
gcd(xd-yd,xd) = gcd((xd-yd)/2,xd) = gcd(xd,yd);
OK;
(3)分解质因数:
利用分解质因数的方法可以简便的求出两个数的最大公约数,
如:
126=2×3×3×7
396=2×2×3×3×11
126和396的最大公因数是=2×3×3=18