欧几里得算法

通常我们用这个算法是求最大公约数

最简单的代码是

int gcd(int a,int b)
{
return (b > 0) ? gcd(b,a%b) : a;
}

但是递归次数过多也会超时

不如用//因为并查集中find函数也可以递归实现但是呢对于一个时间限制强的就过不去,换成这种非递归就过了

int gcd1(int a,int b)
{
int r;
while(b>0)
{
r = a % b;
a = b;
b = r;
}
return a;
}

在一个就要求不定方程的解了

对于不定方程的解需要明确

对于a,b,gcd(a,b)一定存在 ax + by = gcd(a,b)

我们就是要找这样的根

如何利用一开始的欧几里得公式呢

你想想对于b,a % b,gcd(b,a%b)

是不是也存在 bx + a% b *y = gcd(b,a %b)

又因为gcd(b , a%b) = gcd(a,b)

所以我们找到了等式

则:ax1 + by1 = bx2 + (a mod b) y2;
即:ax1 + by1 = bx2 + (a - [a / b] * b) y2 = ay2 + bx2 - [a / b] * by2;
也就是ax1 + by1 == ay2 + b(x2-[a/b]*y2);
根据恒等定理得:x1=y2; y1=x2-[a/b]*y2;

所以我们想求的x和y要由gcd后x2,y2来决定

而gcd()结束的条件是b = 0
我们不妨设 a>b。
1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;

所以在递归的基础上,我们还要进行层层x与y的更新

#include
#include
using namespace std;
int x,y,retgcd;
int exe(int a,int b)
{
	if(b == 0)
	{
		x = 1;
		y = 0;
		return retgcd = a;
	}
	else
	{
		exe(b,a % b);
		int temp = x;
		x = y;
		y = temp - (a / b) * y;
	}
}
int main()
{
	int a,b;  
	while(cin>>a>>b)
	{
		exe(a,b);
		printf("%d = (%d) * %d + (%d) * %d\n",retgcd,x,a,y,b);  
	}
	return 0;  
} 





你可能感兴趣的:(算法思想,算法入门)