1. 程式人生 > >HDU - 1098 - Ignatius's puzzle - ax+by=c

HDU - 1098 - Ignatius's puzzle - ax+by=c

ace lse 證明 nat long long bool namespace 枚舉 不知道

http://acm.hdu.edu.cn/showproblem.php?pid=1098

其實一開始猜測只要驗證x=1的時候就行了,但是不知道怎麽證明。
題解表示用數學歸納法,假設f(x)成立,證明f(x+1)成立需要什麽條件。

代入之後發現有很多二項式系數,導致他們都是65的倍數,剩下的恰好就是 f(x) 和 18+ka 。

那麽只需要找到最小的a使得 18+ka是65的倍數。

題解說,畢竟65畢竟小,可以枚舉a。因為a+65與a的對65的余數是一樣的,所以只要枚舉0到64就可以了。

我的想法是用擴展歐幾裏得求這個的解。

首先由裴蜀定理 ax+by=c 有解,當且僅當gcd(a,b)|c

那麽 18+ka=65t 即 -ka+65t=18 求a的最小非負整數解。套方程的模板。

忘記寫解方程的返回值導致返回一個任意值,有毒。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

//擴展歐幾裏得算法:返回 g=gcd(a,b) ,以及對應的等式 ax+by=g 的解
ll exgcd(ll a,ll b,ll &x,ll &y) {
    if(!a&&!b)
        return -1;
    if(!b) {
        x=1,y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

bool Liner_qu(ll a, ll b, ll c, ll &x, ll &y) {
    if(a==0) {
        if(b==0) {
            if(c==0) {
                x=0;
                y=0;
                return true;
            } else {
                return false;
            }
        }
        if(c%b==0) {
            x=0;
            y=c/b;
            return true;
            //0x+by=c
        } else
            return false;
    }
    if(b==0) {
        if(c%a==0) {
            x=c/a;
            y=0;
            return true;
            //ax+0y=c
        } else {
            return false;
        }
    }
    ll g=__gcd(a,b);
    if(c%g){
        return false;
    }
    //裴蜀定理

    ll k=c/g;
    exgcd(a,b,x,y);
    //ax+by=g的解
    x *= k; // 任意一解
    y *= k;

    ll tx = x;

    x %= b; //最小解
    if(x<0)
        x += abs(b); //最小非負整數解
    k=(tx-x)/b;
    y += k*a; //對應的y的解
    return true;
}


ll F(int k) {
    int a;
    {
        if(k%5==0||k%13==0)
            return -1;
        else {
            a=1;
            while((k*a+18)%65!=0) {
                a++;
            }
            return a;
        }
    }
}

ll G(int k) {
    ll a,b,c,x,y;
    a=-k;
    b=65;
    c=18;

    bool flag=Liner_qu(a,b,c,x,y);

    if(flag) {
        return x;
    } else {
        return -1;
    }
}

int main() {
    int k;
    while(cin>>k) {
        ll a,b,c,x,y;
        a=-k;
        b=65;
        c=18;

        bool flag=Liner_qu(a,b,c,x,y);

        if(flag){
            cout<<x<<endl;
        }
        else{
            cout<<"no"<<endl;
        }
    }

    /*for(int k=1; k<=10000; k++) {
        ll s1=F(k);
        ll s2=G(k);
        if(s1!=s2) {
            cout<<"k="<<k<<endl;
            cout<<s1<<endl<<s2<<endl;
        }
    }*/
}

HDU - 1098 - Ignatius's puzzle - ax+by=c