poj2142_The Balance

来源:互联网 发布:网络诈骗八千 编辑:程序博客网 时间:2024/06/04 16:50
#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 = dx = (d - b * y) / ax + y = (1 - b / a) * y + d / aif b >= a    最大化y (保证y <= d / b)else    最小化y2.a * x - b * y = d<=>a * x + b * (-y) = d设y' = -yx + y = (b / a + 1) * y + d / aso 最小化y扩展欧几里得求y'的通解y"通过y"求绝对值最小的负的特解s = a / gcd(a, b)y = -(y" % s - s) % s同理考虑 b * y - a * y = dHINT在情况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;}