最大公约数

(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,也就是一个数和其自身的公约数仍是其自身。
gcd(ka,kb)=k gcd(a,b),也就是最大公约数运算和倍乘运算可以交换。特殊地,当k=2时,说明两个偶数的最大公约数必然能被2整除。
当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

posted @ 2013-05-13 20:26  简洁是智慧的灵魂  阅读(409)  评论(0编辑  收藏  举报