HDU - 1098 - Ignatius's puzzle - ax+by=c
阿新 • • 發佈:2019-04-20
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