方法一:
/*==========================================================*\ | [扩展眼欧几里德]给定 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;
}