POJ2142The Balance扩展欧几里得

来源:互联网 发布:理财入门知乎 编辑:程序博客网 时间:2024/06/11 20:01
题目:http://poj.org/problem?id=2142

 

题意:有两种类型的砝码质量分别为,要求称出质量为的物品,要求的数量的数量的和

     最小,如果有多个最小值,取最小的。

 

分析:扩展欧几里得求出特解后,把转化为最小正值,即,若

     求出的为负值,则把变正,意思就是砝码放置的位置有左右之分,可以左面的减去右面的,也可以右面

     的减去左面的。同理,再求出为最小合法正值时的解,将这两种情况比较取小的即可。


收获:

这题最初求出来的一组特解x,y中必定是一正一负的,因为砝码的数量不可能为负,所以就相当于用扩展欧几里德求一组解,且|x| + |y|最小。由拓展欧几里德求得x = x0 + b/gcd(a,b)*t, y = y0 + a/gcd(a,b)*t  (其中t为任意整数) ,经过分析所求x+y或者|x| + |y|是满足单调性的,只要x越小或者y越小就行,两者比较下即可。


#include<iostream>#include<cstring>#include<cstdio>using namespace std;int gcd(int a, int b){    return b ? gcd(b, a%b) : a;}void extend_Euclid(int a, int b, int &x, int &y){    if(b == 0)    {        x = 1;        y = 0;        return ;    }    extend_Euclid(b, a%b, x, y);    int tmp = x;    x = y;    y = tmp - (a/b)*y;}int main(){    int a, b, n, x, y;    while(scanf("%d%d%d", &a, &b, &n) != EOF)    {        if(a+b+n == 0) break;        int d = gcd(a, b);        a /= d;        b /= d;        n /= d;        extend_Euclid(a, b, x, y);        int tx = x * n;        tx = (tx + b*n) % b;        int ty = (n - a*tx) / b;        if(ty < 0) ty = -ty;        y *= n;        y = (y + a*n) % a;        x = (n - b*y) / a;        if(x < 0) x = -x;        if(x + y > tx + ty)        {            x = tx;            y = ty;        }        printf("%d %d\n", x, y);    }    return 0;}


0 0