传送门: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;
}