擴充套件歐幾里得【HDU1356】
阿新 • • 發佈:2018-11-12
傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=1356
說實話,我第一眼沒看出來是個exgcd(劃掉)。
擴充套件歐幾里得,這裡就不證明了。
這次我想說的是怎麼求不定方程得通解(這是七年級的題目,我怎麼不記得我初一的時候學過不定方程?!)
上圖片(滑稽)
求出通解以後,題目要求 求出abs(x)+abs(y)的最小值,為啥是abs(x)+abs(y)的最小值呢,因為,(x+y)和(ax+by)最小,而
a|x| = b|y| + c,所以如果x減小,那麼也要減小。故轉化為|x|+|y|最小。
我們保證a>b,那麼|x|+|y|的單調性很容易看出|y|逼近於0的時候,整體答案是最小的。
(swap(a,b)之後,別忘把答案給swap回來,坑死我了)
程式碼程式碼:(那個for的意思是,把|y|為0的時候左右兩邊都看一眼)
#include <bits/stdc++.h> using namespace std; const int INF = 1e9+7; typedef long long ll; ll x,y; ll exgcd(ll &x,ll &y,int a,int b) { ll d = a; if(b!=0) { d = exgcd(y,x,b,a%b); y -= (a/b)*x; } else { x = 1; y = 0; } return d; } int main() { int a,b,d; while(cin>>a>>b>>d) { bool flag = false; if(a<b) { swap(a,b); flag = true; } if(a==0 && b==0 && d==0) break; ll k = d/exgcd(x,y,a,b); ll x0 = x*k, y0 = y*k; ll ansx = abs(x0),ansy = abs(y0); ll t = y0*(d/k)/a; for(int i=t-5;i<=t+5;i++) { ll tmpx = abs(x0+b/(d/k)*i); ll tmpy = abs(y0-a/(d/k)*i); if(abs(tmpx)+abs(tmpy)<abs(ansx)+abs(ansy)) { ansx = tmpx; ansy = tmpy; } } if(flag) { swap(ansx,ansy); } cout<<ansx<<" "<<ansy<<endl; } return 0; }