zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    go语言判断末尾不同的长字符串的方法
    Go语言高级特性总结——Struct、Map与JSON之间的转化
    MacOS使用常用配置
    关于联盟链的一种激励扩张思路(原创)
    密码学中经典算法及应用
    无线网络
    基础的并查集
    找单词
    找零钱
    最大子矩阵
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5841849.html
Copyright © 2011-2022 走看看