您的位置:首页 > 其它

poj 2142 扩展欧几里得

2017-08-30 14:07 351 查看
ax+by=c;
求出通解x = xo + k1*i
y = y0 - k2*i
k1,k2,你懂的.i是变量。
然后根据直线方程。
s = -x0/k1;
e = y0/k2;
min=min{s,e},max=max{s,e}
在区间[min-1,max+1]
这一段内,必取极小值。枚举这一段的 i

其中|x0 - k1 * i| + | y0 - k2*i| 在负无穷到s单调递减 e到正无穷单调递增

#include <iostream>
#include <algorithm>
#include <cstring>
#include <functional>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int MAXN = 100005;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int NIL = -1;
const ll mod = 9973;
#define abs(a) ((a) > 0 ? (a) : (-1 * (a)))
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}

ll extgcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
ll xx, yy;
ll ret = extgcd(b, a % b, xx, yy);
x = yy;
y = xx - (a / b) * yy;
return ret;
}

int main(void)
{
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0);
ll a, b, c;
while (cin >> a >> b >> c)
{
if (!a && !b && !c)
return 0;
ll x, y;
ll g = extgcd(a, b, x, y);

if (c % g == 0)
{
x *= c / g;
y *= c / g;
a /= g;
b /= g;
ll s = -x / b;
ll e = y / a;

ll ansx = abs(x), ansy = abs(y);
for (ll t = min(s, e) - 1; t <= max(s, e) + 1; ++t)
{
if (ansx + ansy > abs(x + b * t) + abs(y - a * t))
ansx = abs(x + b * t), ansy = abs(y - a * t);
else if (ansx + ansy == abs(x + b * t) + abs(y - a * t))
{
if (a * ansx + b * ansy > a * abs(x + b * t) + b * abs(y - a * t))
ansx = abs(x + b * t), ansy = abs(y - a * t);
}
}
cout << ansx << " " << ansy << endl;
}
else
cout << "-1" << endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: