欧几里得算法及其扩展

当大家在学习c语言的时候都会遇到求最大公约数的的问题,这时候我们用的是辗转相除的方法,其实就是欧几里得算法。欧几里得算法的定义:定理:两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数。最大公约数(greatest common divisor)缩写为gcd。

#include
int ExtendEulide(int a,int b)
{
	return b==0? a:ExtendEulide(b,a%b);
}
int main()
{
	printf("%d",ExtendEulide(36,54));
}
当然扩展欧几里得算法其实就是在欧几里得算法的基础上进行了扩展。当我们在用欧几里得算法进行求最大公约数的时候很容易得到如下的推算

gcd(a,b)=gcd(b,amodb)

扩展欧几里得算法用表达式表示:ax+by=gcd(a,b)

这时我们只知道a和b的值,我们可以得到如下的推导

设方程的一个解是:x1,y1于是ax1+by1=gcd(a,b)

设方程的另一个解是x2,y2于是bx2+(amodb)y2=gcd(b,amodb)

由于gcd(a,b)=gcd(b,amodb)

所以

ax1+y1=bx2+(amodb)y2

由于取余数的运算在计算机中可以写成amodb=a-(a/b)*b

所以

ax1+y1=bx2+(a-(a/b)*b)*y2

进一步的变换得到

ax1+by1=ay2+bx2-(a/b)*b*y2

ax1+by1=ay2+b(x2-(a/b)*y2)

所以根据两边等式的性质

x1=y2;y1=x2-(a/b)*y2;

这时一个递推式,但我们令b=0时由于gcd(a,b)=gcd(c,0)(c就是最大的公约数)

发现xc+y*0=c的一个解是x=1,y=0

所以当我们用欧几里得算法进行求解的时候当求得最大公约数的时候就是递归进行到底的时候,所以我们很容易就可以在欧几里得算法的基础上进行扩展


#include
int ExtendEulide(int a,int b,int *x,int *y)
{

	if(b==0)//递归结束,后续工作就是系统从用户的调用栈中层层返回
	{
		*x=1;
		*y=0;
		return a;
	}

	int result=ExtendEulide(b,a%b,x,y);
	int temp= *x;//记录一下x2
	*x=*y;//x1=y2
	*y=temp-(*y)*(a/b);//y1=x2-(a/b)*y2
	

	return result; 
}


void main()
{
	int x, y;
	int c=ExtendEulide(36,56,&x,&y);
	printf("x:%d,y:%d,gcd(a,b):%d",x,y,c);
}




你可能感兴趣的:(算法)