题目:http://poj.org/problem?id=2142
题意:给你3个数a,b,m,其中a,b代表两种砝码的权值,m代表要称量的物品的重量。两种砝码分别用x,y个称出物品的重量,使得x+y最小,若有几种解,取ax+by最小的那组解。
题意:给你3个数a,b,m,其中a,b代表两种砝码的权值,m代表要称量的物品的重量。两种砝码分别用x,y个称出物品的重量,使得x+y最小,若有几种解,取ax+by最小的那组解。
分析:http://blog.youkuaiyun.com/w20810/article/details/43269303用扩展欧几里德求出特解(x0,y0)。设a>b,d=gcd(a,b),那么|x|+|y|=|x0+b/d*t|+|y0-a/d*t|,其中t为整数。在t=y0*d/a附近,使得|x|+|y|最小。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
LL my_abs(LL x)
{
if(x<0)
return -x;
else
return x;
}
void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if(b==0)
{
d=a;
x=1;
y=0;
}
else
{
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
LL a,b;
struct node
{
LL x,y;
bool operator < (const node &t) const
{
if(x+y!=t.x+t.y)
return x+y<t.x+t.y;
else
return a*x+b*y<t.x*a+t.y*b;
}
}s[3];
int main()
{
LL m,x,y,d;
LL ansx,ansy;
while(cin>>a>>b>>m,(a+b+m))
{
bool fg=0;
if(a<b)
{
fg=1;
swap(a,b);
}
exgcd(a,b,d,x,y);
LL x0=x*m/d;
LL y0=y*m/d;
LL t=y0*d/a;
s[0].x=my_abs(x0+b/d*(t-1));
s[0].y=my_abs(y0-a/d*(t-1));
s[1].x=my_abs(x0+b/d*(t));
s[1].y=my_abs(y0-a/d*(t));
s[2].x=my_abs(x0+b/d*(t+1));
s[2].y=my_abs(y0-a/d*(t+1));
sort(s,s+3);
ansx=s[0].x;
ansy=s[0].y;
if(!fg)
cout<<ansx<<" "<<ansy<<"\n";
else
cout<<ansy<<" "<<ansx<<"\n";
}
return 0;
}