首页 > 代码库 > poj The Luckiest number

poj The Luckiest number

                                     The Luckiest numbe


题目:

    在满足|x| + |y|最小时候,让a*|x| + b*|y|最小。求:|x| + |y|最小值。

算法:

    同余式的求解运用。

    解体步骤:

    1、先用gcd判断是否有解。(c%g == 0有解)

    2、对式子求最简式。a‘ = a/g ; b‘ = b/g; c‘ = c/g;

    3、运用扩展欧几里得求解x,y的值。

    4、判断当x,y分别求得最小正整数解时候的大小。

    5、确定最后答案。

    处理过程中有一些细节: 

    1、对求的x,y并不是正确的x,y值。要x = x * c; y = y * c

    2、保证x或y是正数.(x%b + b)%b \ (y%a + a)%a

    

/*
    1、|x| + |y|最小
    2、在1相同的时候a*|x| + b*|y|最小
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

typedef long long LL;

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

void extgcd(LL a,LL b,LL& d,LL& x,LL& y){
    if(!b) { d = a; x = 1; y = 0; }
    else { extgcd(b,a%b,d,y,x); y -= x * (a/b); }
}

int main()
{
    LL a,b,c;
    while(cin >> a >> b >> c){
        if(a == 0&&b == 0&&c == 0)break;
        LL d = gcd(a,b);

        a /= d; b /= d; c /= d;
        LL x,y;
        extgcd(a,b,d,x,y);

        LL x1,y1,x2,y2;

        //y 取得最小正整数
        y1 = y * c;
        y1 = (y1 % a + a) % a;
        x1 = (c - b*y1) / a;
        if(x1 < 0) x1 = -x1;  //砝码个数非负

        //x取得最小正整数
        x2 = x * c;
        x2 = (x2 % b + b) % b;
        y2 = (c - a*x2) / b;
        if(y2 < 0) y2 = -y2;

        if(x1 + y1 < x2 + y2){x = x1; y = y1;}
        else {x = x2; y = y2;}

        cout << x << " " << y << endl;
    }
    return 0;
}






/*
700 300 200
500 200 300
500 200 500
275 110 330
275 110 385
648 375 4002
3 1 10000
0 0 0
*/






poj The Luckiest number