Uva 10104 Euclid Problem |x|+|y|最小解 扩展欧几里得

/*
*   url: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1045
*   stratege: 求ax+by=gcd(a,b), |x|+|y|的和的x,y,的解, 扩展欧几里得,分四种情况考虑
*   status:10541367	10104	Euclid Problem	Accepted	C++	0.176	2012-08-30 05:31:09
*   Author: johnsondu
*/

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

#define LL long long 

void Euclid (LL a, LL b, LL &d, LL &x, LL &y)
{
    if (b == 0)
    {
        d = a ;
        x = 1 ;
        y = 0 ;
        return ;
    }
    Euclid (b, a%b, d, x, y) ;
    LL tmp = x ;
    x = y ;
    y = tmp - a/b*y ;
}

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

int main ()
{
    #if 0
    freopen ("date.txt", "r", stdin) ;
    #endif 
    LL a, b, d, x, y, i, c ;
    LL x0, y0 ;
    LL ax, ay ;
    LL tx, ty, mins ;
    while (scanf ("%lld%lld", &a, &b) != EOF)  // 扩展欧几里得,求ax+by = Gcd (a,b)的最小正整数解
    {                                           //分为4种情况.x的最小正整数,y的最小正整数,x-周期,y-周期
        Euclid (a, b, d, x, y) ;               //x,y 为 特解, d为a,b 的最大公约数
        x0 = (x%b + b) % b ;           //x的最小正整数解 (1)
        y0 = (d-a*x0)/b ;              //相应的y值
        mins = abs (x0) + abs(y0) ; 
        tx = x0, ty = y0 ;
        
        x0-=b ;                        //x的最小正整数解-x的周期  (2)
        y0 = (d-a*x0)/b ;              //此时相应的y
        if (abs(x0) + abs(y0) < mins)
        {
            mins = abs(x0) + abs(y0) ;
            tx = x0 ;
            ty = y0 ;
        }
        
        y0 = (y%a + a) % a ;           //y的最小正整数解 (3)
        x0 = (d-b*y0)/a ;              //此时对应的x
        
        if (abs(x0) + abs(y0) < mins)
        {
            mins = abs(x0) + abs(y0) ;
            tx = x0 ;
            ty = y0 ;
        }
        
        y0 -= a ;                      //y的最小正整数解-y的周期
        x0 = (d-b*y0)/a ;              //此时对应的x
        if (abs(x0) + abs(y0) < mins)
        {
            mins = abs(x0) + abs(y0) ;
            tx = x0 ;
            ty = y0 ;
        }
                
        printf ("%lld %lld %lld\n", tx, ty, d) ;      
    }
    return 0 ;
}

你可能感兴趣的:(Uva 10104 Euclid Problem |x|+|y|最小解 扩展欧几里得)