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
代碼: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; }