题目:
http://poj.org/problem?id=2142
题意:有两种类型的砝码质量分别为和
,要求称出质量为
的物品,要求
的数量
和
的数量
的和
最小,如果有多个最小值,取
最小的。
分析:扩展欧几里得求出特解后,把转化为最小正值,即
,
,若
求出的为负值,则把
变正,意思就是砝码放置的位置有左右之分,可以左面的减去右面的,也可以右面
的减去左面的。同理,再求出为最小合法正值时
的解,将这两种情况比较取小的即可。
收获:
这题最初求出来的一组特解x,y中必定是一正一负的,因为砝码的数量不可能为负,所以就相当于用扩展欧几里德求一组解,且|x| + |y|最小。由拓展欧几里德求得x = x0 + b/gcd(a,b)*t, y = y0 + a/gcd(a,b)*t (其中t为任意整数) ,经过分析所求x+y或者|x| + |y|是满足单调性的,只要x越小或者y越小就行,两者比较下即可。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int gcd(int a, int b)
{
return b ? gcd(b, a%b) : a;
}
void extend_Euclid(int a, int b, int &x, int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return ;
}
extend_Euclid(b, a%b, x, y);
int tmp = x;
x = y;
y = tmp - (a/b)*y;
}
int main()
{
int a, b, n, x, y;
while(scanf("%d%d%d", &a, &b, &n) != EOF)
{
if(a+b+n == 0) break;
int d = gcd(a, b);
a /= d;
b /= d;
n /= d;
extend_Euclid(a, b, x, y);
int tx = x * n;
tx = (tx + b*n) % b;
int ty = (n - a*tx) / b;
if(ty < 0) ty = -ty;
y *= n;
y = (y + a*n) % a;
x = (n - b*y) / a;
if(x < 0) x = -x;
if(x + y > tx + ty)
{
x = tx;
y = ty;
}
printf("%d %d\n", x, y);
}
return 0;
}