欧几里得算法:
用来求最小公倍数的一个简单的递归函数。
扩展欧几里得算法:
用来求ax+by = gcd(a,b)(为什么是gcd(a,b),我们后面会讲)这个式子中x和y的一对整数解(不是唯一,还有其他的xy解)。例如:6x+15y=3,这里的3恰好是gcd(6,15),所以算出来的x,y解就是这个式子的一个合理解。
但是只求一组解有时远远不够,而且为了省时间,不妨将每个合理解之间的关系找出来,下面开始寻找规律:我们先算出一对合理解(x1,y1),我们再设另一对(x2,y2),那么可以得到ax1 + by1 = ax2 + by2,变形得a(x1 - x2) = b(y2 - y1),因为a和b存在最小公倍数,所以我们同除gcd(a,b),得到两个互素的a'和b',那么(x1 - x2)也就必然为b'的k倍(因为a和b已经不会有任何倍数关系了),继续求可得到(y2 - y1) = ka'。那么这个式子的所有合理解就可以写成(x1-kb' , y1+ka')。
有了上面的xy解的关系,我们再来讨论c不同的情况,比如:6x + 15y = 9 和6x + 15y = 8。针对这两个情况,我们只需要判断式子中的c和gcd(a,b)的关系就ok了。如果c%gcd==0,则式子有解,且x和y的实际值和通过ax+by = gcd(a,b)求出来的x y值相差c/gcd倍;如果c%gcd != 0,则式子无解。(所以我们之前用的是ax+by = gcd(a,b),而不是其他的方程式。)
不全经过多次修改的代码:
#include <iostream>
#include <cstdio>
using namespace std;
int exgcd(int a, int b, int&x, int&y)
{
if(!b)
{
x=1;
y=0;
return a;//这里的a其实就是最小公倍数,这里return就是相当于把欧几里得算法揉进去。
}
else
{
int r = exgcd(b,a%b,x,y);
int t = x;
x = y;
y = t- a/b*y;
return r;
}
}
int main()
{
//ax + by = c
int a,b,c;
while(cin>>a>>b>>c)
{
bool flag = false;
int x,y;
int gcd = exgcd(a,b,x,y);
if(c%gcd != 0)
{
cout << "无解" << endl;
}
else
{
int k = c/gcd;
x*=k,y*=k; //得到了满足方程的一组解
//下面是把x和y都变成正数,不是必须的
/*k = 1;
int ax = a/gcd;
int bx = b/gcd;
while(x-k*bx <=0 || y+k*ax <= 0)
{
k++;
}
x = x-k*bx;
y = y+k*ax;*/
printf("%d*%d + %d*%d = %d\n", a,x,b,y,c);
}
}
return 0;
}