这几天补补数学····做点基础题
题目描述
现有质量为a和b的砝码,数量不限
要求在天平上称出质量为d的物品,天平左右均可放砝码
求一种可行方案,要求:放置砝码数量尽可能少;数量相同时,总质量尽可能少
不会无解
分析
明显转化为ax+by=c,现在问题是让|x|+|y|最小。
若其最小,此时x或y肯定是最小的正整数解,因为一个更优,我们让他一直减下去嘛。
naive的想法是x每次减b,y每次减a,但是这样最后减出来的不是最小的,因为a,b不一定互质,减的东西可以是b/gcd(a,b),那么a,b,c都除(a,b)就好了。
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
typedef double db;
typedef long long ll;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
int a,b,c,d,x,y,t,i,k,ax,ay;
int exgcd(int a,int b)
{
if (!b)
{
x=1;
y=0;
return a;
}
int d=exgcd(b,a%b);
int xx=y;
int yy=x-a/b*y;
x=xx;y=yy;
return d;
}
int main()
{
freopen("1.in","r",stdin);
while (1)
{
scanf("%d %d %d",&a,&b,&c);
if (!a) break;
d=exgcd(a,b);
k=c/d;
x=x*k;
y=y*k;
a/=d;
b/=d;
c/=d;
//minimize x
ax=(x%b+b)%b;
ay=(c-ax*a)/b;
//minimize y
y=(y%a+a)%a;
x=(c-y*b)/a;
if (abs(x)+abs(y)<abs(ax)+abs(ay)||(abs(x)+abs(y)==abs(ax)+abs(ay)&&b<a)) ax=x,ay=y;
printf("%d %d\n",abs(ax),abs(ay));
}
return 0;
}