当前位置: 代码迷 >> 综合 >> poj - 2142 - The Balance
  详细解决方案

poj - 2142 - The Balance

热度:46   发布时间:2024-01-10 13:53:14.0

题意:用x个a毫克的砝码与y个b毫克的砝码恰好称得质量为d毫克的阿斯匹林,求使x+y最小的x和y。

题目链接:http://poj.org/problem?id=2142

——>>好题。因为欧几里德扩展算法只能求ax + by = gcd(a, b);所以,先求a, b的最大公约数gcd_ab,对于ax + by = d,令a, b, d同除以gcd_ab,然后可求得(a/gcd_ab)x + (b/gcd_ab)y = 1的最小整数解,然后将求得的这组解乘以d/gcd_ab得x0, y0,就是ax + by = d一组解,由数论知识得ax + by = d的所有解为: x = x0 - bt, y = y0 + at(t为参数),那么,要使|x|+|y|最小,可令x = 0求得一组解,再令y = 0求得一组解,两组比较取较小者就好。

#include <cstdio>using namespace std;typedef long long LL;LL gcd(LL a, LL b)
{return b == 0 ? a : gcd(b, a%b);
}
void Euler_extends(LL a, LL b, LL& x, LL& y)
{if(!b){x = 1;y = 0;}else{Euler_extends(b, a%b, y, x);        //白书加强版的写法,个人觉得,妙极!y -= a / b * x;}
}
int main()
{LL a, b, d, x, y;while(~scanf("%I64d%I64d%I64d", &a, &b, &d)){if(!a && !b && !d) return 0;LL gcd_ab = gcd(a, b);a /= gcd_ab;b /= gcd_ab;d /= gcd_ab;Euler_extends(a, b, x, y);LL y1 = (y * d % a + a) % a;LL x1 = (d - b * y1) / a;if(x1 < 0) x1 = -x1;LL x2 = (x * d % b + b) % b;LL y2 = (d - a * x2) / b;if(y2 < 0) y2 = -y2;if(x1+y1 < x2+y2) printf("%I64d %I64d\n", x1, y1);else printf("%I64d %I64d\n", x2, y2);}return 0;
}