poj - 2142 - The Balance
1496 ワード
題意: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はx 0,y 0を得て、ax+by=dの1組の解で、数論の知識からax+by=dのすべての解を得ます:x=x 0-bt,y=y 0+at(tはパラメータです)、それでは|x|+|y|を最小にして、x=0に1組の解を求めて、更にy=0に1組の解を求めて、2組は比較的に小さい者を取るのが良いです.
タイトルリンク: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はx 0,y 0を得て、ax+by=dの1組の解で、数論の知識からax+by=dのすべての解を得ます:x=x 0-bt,y=y 0+at(tはパラメータです)、それでは|x|+|y|を最小にして、x=0に1組の解を求めて、更にy=0に1組の解を求めて、2組は比較的に小さい者を取るのが良いです.
#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
", x1, y1);
else printf("%I64d %I64d
", x2, y2);
}
return 0;
}