题目: http://acm.hdu.edu.cn/showproblem.php?pid=1356
题意:
Sample Input
700 300 200 500 200 300 500 200 500 275 110 330 275 110 385 648 375 4002 3 1 10000 0 0 0
Sample Output
1 3 1 1 1 0 0 3 1 1 49 74 3333 1
输入a b c三个值,a !=b,a b分别代表两种砝码,要称出质量为 c 物体,a,b可无限使用,设需要x个a,y个b ,输出x,y使x+y最小,若有多组解,输出a*x+b*y最小的那组。
思路:
先处理使a>=b;
a*x+b*y=gcd(a,b),通解x=x+b/d*k;y=y-a/d*k;则 |x|+|y|=| x+b/d*k |+| a/d*k-y |,因为a/d>=b/d,所以当k变化时,a/d*k要变化得快一些,因此只要|a/d*k-y| 在0附近即是最小值。
#include<stdio.h>
typedef int LL;
LL x,y;
LL flag;
void xchg(LL &a,LL &b)
{
LL t;
flag=0;
if(a<b)
{
flag=1;
t=a;
a=b;
b=t;
}
}
LL exgcd(LL a,LL b)
{
LL ans;
if(b==0)
{
x=1;
y=0;
return a;
}
ans=exgcd(b,a%b);
LL t=x;
x=y;
y=t-a/b*y;
return ans;
}
LL abs(LL m)
{
if(m>0)return m;
return -m;
}
int main()
{
LL a,b,c,d,i;
while(scanf("%d%d%d",&a,&b,&c)!=EOF)
{
if(a==0&&b==0&&c==0)break;
xchg(a,b);
d=exgcd(a,b);
x=c/d*x;
y=c/d*y;
LL k=y/(a/d);
LL minn=99999999,ans1,ans2;
k--;
for(i=0;i<3;i++)
{
LL xx=b/d*k+x;
LL yy=a/d*k-y;
if( abs(xx)+abs(yy)<minn)
{
ans1=abs(xx);
ans2=abs(yy);
minn=ans1+ans2;
}
else
if( abs(xx)+abs(yy)==minn)
{
if(a*abs(xx)+b*abs(yy)<a*ans1+b*ans2)
{
ans1=abs(xx);
ans2=abs(yy);
minn=ans1+ans2;
}
}
k++;
}
if(flag)
printf("%d %d\n",ans2,ans1);
else
printf("%d %d\n",ans1,ans2);
}
return 0;
}