Solve Equations HackerRank 扩展欧几里德 && 数学

https://www.hackerrank.com/contests/infinitum16-firsttimer/challenges/solve-equations

给定一条方程a*x + b*y = c

保证有解的情况下,我们要求一个点,满足x > 0且 这个点到原点的欧几里德距离最短

根据扩展欧几里德算法,我们能求得一组(x1,y1)满足x1 > 0的解,第一个x>0的解。

然后通解就是x2 = x1 + b/abgcd*k  y2 = y1 - a/abgcd*k

如果(x2,y2)就是所求,那么k一定要大于0,因为小于0的话,加上x1的时候会使得x2<0,这是因为x1是所有解中最小的正整数了,在它左边的解,必定是小于0的。

那么k的范围就是 >= 0了

把式子展开  x2*x2 + y2*y2

得到一条关于t的二次方程,如果对称轴在原点左边,那么t=0就是ans

否则,取对称轴。因为可能是小数,所以取整了,判断对称轴左右两个点就好了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
LL abGCD;
LL gcd (LL a, LL b) {
    if (a % b == 0) return b;
    else return gcd (b, a % b);
}
LL exgcd (LL a,LL mod,LL &x,LL &y) {
    if (mod==0) {
        x=1;
        y=0;
        return a;
    }
    LL g=exgcd(mod,a%mod,x,y);
    LL t=x;
    x=y;
    y=t-(a/mod)*y;
    return g;
}
LL get_min_number (LL a,LL b,LL c,LL &x,LL &y) {
    abGCD = gcd(a,b);
    if (c%abGCD != 0) return -1;
    a /= abGCD;
    b /= abGCD;
    c /= abGCD;
    LL tx,ty;
    exgcd(a,b,tx,ty);
    x = tx*c;
    y = c*ty;
    LL temp_x = x;
    x %= b;
    if (x<=0) x += b;
    LL k = (temp_x-x)/b;
    y += k*a;
    return 1;
}

void work () {
    LL a, b, c;
    cin >> a >> b >> c;
    LL x, y;
    get_min_number (a, b, c, x, y);
//    LL bb=abs(b/gcd(a,b));
//    LL aa=abs(a/gcd(a,b));
//    while(x<0) x += bb;
//    while(x*a+b*y!=c) y += aa;
//    cout << x << " " << y << endl;
    LL c1 = b / abGCD;
    LL c2 = - a / abGCD;
    LL A = c1 * c1 + c2 * c2;
    LL B = 2 * y * c2 + 2 * x * c1;
    LL C = x * x + y * y;
    if (B > 0) {
        cout << x << " " << y << endl;
    } else {
        LL t = B / (-2 * A);
        LL mx = A*t*t + B*t + C;
        t++;
        LL tmax = A*t*t + B*t + C;
        if (tmax > mx) {
            t--;
        }
        cout << x + c1*t << " " << y + c2*t << endl;
    }
}

int main () {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    int t;
    cin >> t;
    while (t--) work ();
    return 0;
}
View Code

 

1
4 1 82

posted on 2016-09-05 12:26  stupid_one  阅读(339)  评论(0编辑  收藏  举报

导航