#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
/**
题目大意
用a, b两种砝码称出d
答案先最小化x + y
后最小化a * x + b * y
思路
分两种
1.
a * x + b * y = d
x = (d - b * y) / a
x + y = (1 - b / a) * y + d / a
if b >= a
最大化y (保证y <= d / b)
else
最小化y
2.
a * x - b * y = d
<=>
a * x + b * (-y) = d
设y' = -y
x + y = (b / a + 1) * y + d / a
so 最小化y
扩展欧几里得求y'的通解y"
通过y"求绝对值最小的负的特解
s = a / gcd(a, b)
y = -(y" % s - s) % s
同理考虑 b * y - a * y = d
HINT
在情况1和情况2 x + y 相等时 情况1的 a * x + b * y 更小
*/
using namespace std;
int exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
int r = exgcd(b, a % b, x, y);
int temp = x;
x = y;
y = temp - a / b * y;
return r;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
int a, b, d, x, y, x1, y1, temp1, temp2;
while (scanf("%d %d %d", &a, &b, &d) != EOF && a)
{
int g = exgcd(a, b, temp1, temp2);
int s = a / g;
temp2 *= d / g;
y = -(temp2 % s - s) % s;
x = (d + b * y) / a;
if (b <= a)
{
y1 = (temp2 % s + s) % s;
x1 = (d - b * y1) / a;
if (x1 >= 0 && x1 + y1 <= x + y)
{
x = x1;
y = y1;
}
}
if (b > a)
{
temp2 = (temp2 % s + s) % s;
while (temp2 + s <= d / b)
{
temp2 += s;
}
temp1 = (d - b * temp2) / a;
if (temp2 <= d / b && temp1 + temp2 <= x + y)
{
x = temp1;
y = temp2;
}
}
g = exgcd(b, a, temp2, temp1);
s = b / g;
temp1 *= d / g;
temp1 = -(temp1 % s - s) % s;
temp2 = (d + a * temp1) / b;
if (temp1 + temp2 < x + y)
{
x = temp1;
y = temp2;
}
printf("%d %d\n", x, y);
}
return 0;
}
poj2142_The Balance
最新推荐文章于 2019-04-13 21:27:48 发布