2020牛客寒假算法基礎集訓營5 部分題解(BDEH)

B: 牛牛戰隊的比賽地(二分作法)
題意:二維平面給定n個點,在x軸找一點使獲得n個點距離的最大值最小。ios

思路:
咱們能夠將問題轉化爲在x軸找到一個圓心,使得該圓包含這n個點且半徑最小,這樣就變成了最小圓覆蓋問題。有關於最大值最小此類問題,咱們第一個想到的就應該是二分了,關鍵在於二分半徑後如何check呢?
首先咱們須要明白這樣一個前提,也是解題的關鍵點:一個半徑爲R的圓,咱們任意在圓上或圓內找一個點,也作半徑爲R的圓,那麼這個圓必定會包含以前那個圓的圓心。
明白了這個,問題就easy了,咱們將二分獲得的半徑R,把n個點都拿來作這樣半徑爲R的圓,與x軸相交的部分,說明圓心可能落在這一範圍內,而後咱們只要看這些區域是否產生矛盾就行了。好比點1與x軸相交範圍爲[3,6],點2爲[7,10],沒有相交的部分,顯然答案矛盾,即不存在半徑爲R的圓能夠包含所有點。c++

#include <bits/stdc++.h>
#define x first
#define y second
#define d double
using namespace std;
const int N = 2e5 + 5;
int n;
pair<d, d> p[N];

bool check(d o)
{
    d l, mi = -1e18, ma = 1e18;
    for (int i = 1; i <= n; i++)
    {
        if (o < fabs(p[i].y))
            return false;
        l = sqrt(o - p[i].y) * sqrt(o + p[i].y); ///等價於sqrt(o*o-p[i].y*p[i].y)
        mi = max(mi, p[i].x - l);
        ma = min(ma, p[i].x + l);
    }
    return mi <= ma; ///判斷最大的左端點<=最小的右端點便可
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> p[i].x >> p[i].y;
    d l = 0, r = 1e18, mid;
    int t = 250;
    while (t--)
    {
        mid = (l + r) / 2.0;
        if (check(mid))
            r = mid;
        else
            l = mid;
    }
    cout << fixed << setprecision(6) << r;
    return 0;
}

 

D:牛牛與牛妹的約會 (貪心)
題解:咱們先明確什麼時候開根號走會更優,即:x - x^(1/3) > 1,解得x>2.3247179,所以咱們貪心的按開根號走直到x<=2.3247179,同時維護最小值便可。spa

#include <bits/stdc++.h>
using namespace std;
double cal(double x)
{
    double l = 0, r = x, mid;
    int q = 50;
    while (q--)
    {
        mid = (l + r) * 0.5;
        if (mid * mid * mid >= x)
            r = mid;
        else
            l = mid;
    }
    return r;
}
int main()
{
    int t;
    while (~scanf("%d", &t))
    {
        while (t--)
        {
            double a, b;
            scanf("%lf%lf", &a, &b);
            double now = 0, ans = fabs(a - b);
            if (a >= 0)
            {
                while (a >= 2.3247179)
                {
                    now += 1.0;
                    a = cal(a);
                    ans = min(ans, fabs(a - b) + now);
                }
            }
            else if (a < 0)
            {
                a = -a;
                b = -b;
                while (a >= 2.3247179)
                {
                    now += 1.0;
                    a = cal(a);
                    ans = min(ans, fabs(a - b) + now);
                }
            }
            printf("%.9f\n", ans);
        }
    }
    return 0;
}

 

E: Enjoy the game (博弈)
題解:多寫幾個就看出來了,是二次冪後手勝,不然先手勝。code

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    if (!(n & (n - 1)))    ///判斷是否爲2次冪
        cout << "Alice";
    else
        cout << "Bob";
    return 0;
}

 

H:Hash (進制轉化)
題解:
x%mod=p  不可貴到  (x+mod)%mod=p
因此字符串加個mod就能夠了,判一下長度是否還爲6便可。blog

#include <bits/stdc++.h>
using namespace std;
char s[20], a[105];
int mod, k, x;
int main()
{
    while (~scanf("%s%d", s, &mod))
    {
        memset(a, 0, sizeof(a));
        k = x = 0;
        for (int i = 0; i < 6; i++)
            x = x * 26 + s[i] - 'a';  ///轉爲10進制
        x += mod;
        while (x)      ///轉回26進制
        {
            a[++k] = x % 26;
            x /= 26;
        }
        if (k <= 6)
        {
            if (k < 6)  ///長度不夠6補a便可
                k++;
            for (int i = k; i >= 1; i--)
                printf("%c", a[i] + 'a');
        }
        else
            printf("-1");
        puts("");
    }
    return 0;
} 
相關文章
相關標籤/搜索