POJ2142 The Balance

传送门

这道题是一道相当不错的不定方程的题!

题目大意是要我们用若干个两种给定质量的砝码称出给定质量的物品,其中满足使用砝码总数最小,如果有多组解输出砝码质量最小的一组解。

其实转化一下我们还是要求ax+by=c的一组解……

这个当然很好求,之后既然要求砝码总数最小,我们只要让x或者y最小即可,然后比较两者总数大小。最小的正整数解很好求,这样的话对应的另一个值就是固定的(如果是负数要取相反数,相当于放在天平不同位置)

至于为什么取最小,因为不定方程的通解是有公式的,如果我们不取最小的正整数解,那么另一种砝码必然比原来更多,不可能更优(即使是负数也会取相反数)

然后其实我个人认为好像不用管质量最小……反正我没管就过了,也许是数据有点水。

看一下代码。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
#define pb push_back
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('
')

using namespace std;
typedef long long ll;
const int M = 40005;
const int N = 2000005;
const int INF = 1000000009;
const ll mod = 51123987;

ll read()
{
    ll ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
    if(ch == '-') op = -1;
    ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
    ans *= 10;
    ans += ch - '0';
    ch = getchar();
    }
    return ans * op;
}

ll a,b,c,x,y,G,d,kx,ky,sx,sy;

ll gcd(ll a,ll b)
{
    return (!b) ? a : gcd(b,a%b);
}

ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b)
    {
    x = 1,y = 0;
    return a;
    }
    d = exgcd(b,a%b,y,x);
    y -= a / b * x;
    return d;
}

int main()
{
    while(1)
    {
    a = read(),b = read(),c = read();
    if(!a && !b && !c) break;
    G = gcd(a,b);
    a /= G,b /= G,c /= G;
    exgcd(a,b,x,y);
    kx = (x + b) % b,kx *= c,kx %= b;
    ky = (c - a * kx) / b;
    if(ky < 0) ky = -ky;
    sy = (y + a) % a,sy *= c,sy %= a;
    sx = (c - b * sy) / a;
    if(sx < 0) sx = -sx;
    if(sx + sy < kx + ky) printf("%lld %lld
",sx,sy);
    else printf("%lld %lld
",kx,ky);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/captain1/p/9781280.html