UVALive_6170_Esspe-Peasee(求解不定方程)

題型:數論


題意:求解不定方程ax+by=c,要求x+y最小且x、y非負,如果多個x+y,x儘量小。


分析:

擴展歐幾里得求解方程,注意格式問題。


代碼:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>

#define LL long long
using namespace std;

/**
不定方程的求解思路:
擴展gcd求出ax+by=gcd(a,b)=d的一組特解(x0,y0)
如果c%d!=0,無解

a0 = a/d
b0 = b/d
x0 = x0*(c/d)
y0 = y0*(c/d)
通解:
       x=x0+k*b0
       y=y0-k*a0

如果要求|x|+|y|最小,有-b0<y<b0
*/

/**求解ax+by=c,x爲非負數的最小解,且如果x和y非負,x+y最小*/
class IndefiniteEquation {
    typedef LL DataType;
    DataType a,b,c;
    DataType x,y;
    /**gcd*/
    DataType gcd(DataType A,DataType B) {
        return B?gcd(B,A%B):A;
    }
    /**擴展gcd*/
    DataType ext_gcd(DataType A,DataType B,DataType &x0,DataType &y0) {
        DataType t,ret;
        if(!B) {
            x = 1;
            y = 0;
            return A;
        }
        ret = ext_gcd(B,A%B,x0,y0);
        t = x0;
        x0 = y0;
        y0 = t-A/B*y0;
        return ret;
    }
public:
    void init(DataType aa,DataType bb,DataType cc) {
        a = aa;
        b = bb;
        c = cc;
    }
    /**false無解,true有解*/
    bool solve() {
        if(c==0) {
            x = y = 0;
            return true;
        }
        if(a==0 && b==0) {
            return false;
        }
        if(a==0) {
            if(c%b) {
                return false;
            } else {
                x = 0;
                y = c/b;
                return true;
            }
        }
        if(b==0) {
            if(c%a) {
                return false;
            } else {
                x = c/a;
                y = 0;
                return true;
            }
        }
        DataType d = gcd(a,b);
        if(c%d) return false;
        a /= d;
        b /= d;
        c /= d;
        d = ext_gcd(a,b,x,y);
        DataType t = c%b;
        x %= b;
        x = (x*t)%b;
        x = (x+b)%b;
        y = (c-(x*a))/b;
        return true;
    }
    /**解x*/
    DataType x0(){
        return x;
    }
    /**解y*/
    DataType y0(){
        return y;
    }

}ts;

void no(){
    puts("Unquibable!");
}
void out(LL x,LL y){
    printf("%lld foom",x);
    if(x!=1) printf("s");
    printf(" and %lld foob",y);
    if(y!=1) printf("s");
    puts(" for a twob!");
}

int main() {
    LL a,b,c;
    while(~scanf("%lld%lld%lld",&a,&b,&c)){
        if(!(a|b|c)) break;
        ts.init(a,b,c);
        bool flag = ts.solve();

        if(flag){
            if(ts.y0()<0) no();
            else{
                out(ts.x0(),ts.y0());
            }
        }
        else{
            no();
        }

    }

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章