方法一:
/*==========================================================*\
| [扩展眼欧几里德]给定 a b d找到满足ax+by=d 的令|x|+|y|最小
| 参考线性同余方程 g=gcd(a,b) , ax0+by0=gcd(a,b)
| 程的一组解: x=x0*d/g; y=y0*d/g;
| 方程的全部解:x..=x+b/g*t y..=y-a/g*t
| |x|+|y|= | x + b/g*t | + | y - a/g*t |
| 这个关于t的函数的最小值应该在|y - a/g*t|为零附近,即t=y*g/a
| 在 y*g/a 附近的两整数点里取t,再直接验证这两点即可。
\*==========================================================*/
int extended_gcd(int a, int b, int & x, int & y)
{
if (b == 0) {
x = 1;
y = 0;
return a;
}
int d = extended_gcd(b, a % b, x, y);
int t = x;
x = y;
y = t - a / b * y;
return d;
}
int main()
{
int a, b, d;
while (scanf("%d%d%d", &a, &b, &d) == 3 && (a || b || d)) {
int tag = 1;
int x0, y0;
if (a < b) {
tag = 0;
swap(a, b);
}
int g = extended_gcd(a, b, x0, y0);
int x = x0 * d / g;
int y = y0 * d / g;
int t1 = y * g / a;
if (t1 * a / g - y >= 0) --t1;
int t2 = t1 + 1;
int x1 = MY_ABS(x + b / g * t1);
int y1 = MY_ABS(y - a / g * t1);
int x2 = MY_ABS(x + b / g * t2);
int y2 = MY_ABS(y - a / g * t2);
if ((x1 + y1 > x2 + y2) || ((x1 + y1 == x2 + y2) && (a * x1 + b * y1 > a * x2 + b * y2))) {//当(|x|+|y|)相等时,比较(a|x|+b|y|)哪个小
if (tag) printf("%d %d\n", x2, y2);
else printf("%d %d\n", y2, x2);
} else {
if (tag) printf("%d %d\n", x1, y1);
else printf("%d %d\n", y1, x1);
}
}
return 0;
}
方法二:
有三种情况:
ax+by=d;(a,b均在左盘)
ax-by=d;(a在左盘,b和d在右盘)
-ax+by=d;(b在左盘,a和d在右盘)
枚举a,求满足条件的解。
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int i,a,b,d,x,y,xx,yy;
int sum1,sum2;
while(cin>>a>>b>>d)
{
if(a==0 && b==0 && d==0)break;
int min1=9000000,min2=9000000;
int t=0;
xx=0;yy=0;
for(i=0; ; i++){
if((d-a*i)%b==0)//ax+by=d 和 ax-by=d 两种情况,用绝对值表示,所以合写成一个if
{
yy=abs((d-a*i)/b);
sum1=i+yy;
sum2=a*i+b*yy;
if(sum1<min1)
min1=sum1,min2=sum2,x=i,y=yy;
else if(sum1==min1 && sum2<min2)
min1=sum1,min2=sum2,x=i,y=yy;
if(i>min1 || i*a>min2)//如果x的值比x+y的值都大或者a*x比a*x+b*y 的值都大了就跳出
break;
}
int l=i*a+d;
if(l>0 && l%b==0)//-ax+by=d的情况
{
yy=l/b;
sum1=i+yy;
sum2=a*i+b*yy;
if(sum1<min1)
min1=sum1,min2=sum2,x=i,y=yy;
else if(sum1==min1 && sum2<min2)
min1=sum1,min2=sum2,x=i,y=yy;
if(i>min1 || i*a>min2)//如果x的值比x+y的值都大或者a*x比a*x+b*y 的值都大了就跳出
break;
}
}
cout<<x<<" "<<y<<endl;
}
return 0;
}