2018 Nowcoder Multi-University Training Contest 5

Practice Linkc++

A. gpaspa

題意:
\(n\)門課程,每門課程的學分爲\(s_i\),績點爲\(c_i\),要求最多刪除\(k\)門課程,使得gpa最高。
gpa計算方式以下:
\[ \begin{eqnarray*} gpa = \frac{\sum s_ic_i}{\sum s_i} \end{eqnarray*} \]code

思路:
首先刪去的課程越多,gpa確定不會變得更差。
因此咱們確定是刪去\(k\)門課程。
考慮二分答案,check的時候要知足:
\[ \begin{eqnarray*} gpa &\leq& \frac{\sum s_ic_i}{\sum s_i} \\ gpa \cdot \sum s_i &\leq& \sum s_ic_i \\ \sum s_i \cdot gpa &\leq& \sum s_ic_i \\ \sum s_i \cdot (gpa - c_i) &\leq& 0 \end{eqnarray*} \]
那麼check的時候貪心選取\(n - k\)個便可。get

代碼:it

#include <bits/stdc++.h>
using namespace std;
 
#define ll long long
#define db double
#define N 100010
#define pii pair <int, int>
#define fi first
#define se second
const db eps = 1e-10;
int n, k; pii a[N];
 
bool ok(db x) {
    vector <db> vec;
    for (int i = 1; i <= n; ++i) {
        vec.push_back(a[i].fi * (x - a[i].se));
    }
    sort(vec.begin(), vec.end());
    db tot = 0;
    for (int i = 0; i < n - k; ++i) {
        tot += vec[i];
    }
    return tot <= 0 || fabs(tot - 0) < eps;
}
 
int main() {
    while (scanf("%d%d", &n, &k) != EOF) {
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i].fi);
        }
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i].se);
        }
        db l = 0, r = 1e3, res = 0;
        while (fabs(r - l) >= eps) {
            db mid = (l + r) / 2;
            if (ok(mid)) {
                l = mid;
                res = mid;
            } else {
                r = mid;
            }
        }
        printf("%.10f\n", res);
    }
    return 0;
}

G. maxio

題意:
給出\(c\)\(n\),要求找到一對\((a, b)\)知足\(1 \leq a, b \leq n\)使得\(gcd(a, b) = c\)而且最大化\(a \cdot b\)class

思路:test

  • \(c > n\)時無解
  • \(c = n\)時選擇\((n, n)\)
  • \(c < n\)時在\([1, \frac{n}{c}]\)中選取兩個互質的數再分別乘上\(c\)

代碼:gc

#include <bits/stdc++.h>
using namespace std;
 
#define ll long long
ll c, n;
 
int main() {
    while (scanf("%lld%lld", &c, &n) != EOF) {
        if (c > n) {
            puts("-1");
            continue;
        }
        ll x = n / c;
        ll res = c * c;
        if (x > 1) {
            res *= x * (x - 1);
        }
        printf("%lld\n", res);
    }
    return 0;
}

J. plansort

題意:
\(n\)我的去住宿,雙人房的價格爲\(p_2\), 三人房的價格爲\(p_3\),要求將\(n\)我的全都安排好住宿的最小代價是多少,不必定剛好住滿。

思路:
大範圍直接除2, 除3, 小範圍暴力dp一下。

代碼:

#include <bits/stdc++.h>
using namespace std;

#define N 1000010
#define ll long long
#define ll long long
ll n, p2, p3;
ll f[N];

ll DFS(int x) {
    if (x <= 0) {
        return 0;
    }
    if (f[x] != -1) {
        return f[x];
    }
    return f[x] = min(p2 + DFS(x - 2), p3 + DFS(x - 3));
}

int main() {
    while (scanf("%lld%lld%lld", &n, &p2, &p3) != EOF) {
        memset(f, -1, sizeof f);
        if (n <= 1000000) {
            printf("%lld\n", DFS(n));
        } else {
            ll res = 1e18;
            ll m;
            for (int i = 0; i < 1000000; ++i) {
                m = n - i;
                res = min(res, p2 * (m / 2) + DFS(i + m % 2));
                res = min(res, p3 * (m / 3) + DFS(i + m % 3));
            }
            printf("%lld\n", res);
        }
    }
    return 0;
}
相關文章
相關標籤/搜索