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; }
1
4 1 82
既然选择了远方,就要风雨兼程~
posted on 2016-09-05 12:26 stupid_one 阅读(339) 评论(0) 编辑 收藏 举报