Educational Codeforces Round 77 (Rated for Div. 2)
比赛链接:https://codeforces.com/contest/1260
A - Heating
题意
给 $c$ 个暖气管装配 $sum$ 个暖气片,每个暖气管的装配花费为所用暖气片个数的平方,求出装配所有暖气管的最少花费。
题解
尽可能地平分即可。
代码
#include <bits/stdc++.h> #define cal(n) ((n) * (n)) using namespace std; void solve() { int c, sum; cin >> c >> sum; cout << cal(sum / c) * (c - sum % c) + cal(sum / c + 1) * (sum % c) << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
B - Obtain Two Zeroes
题意
$0≤a,b≤10^9$,每次可以选择给一个数减去正整数 $x$,给另一个数减去 $2x$,判断能否使二者都减为 $0$ 。
题解
假设 $a≤b$,考虑二者可以减为 $0$ 的情况:
- $b = 2a$
- $a = b = 3x$
所以将 $a,\ b$ 化为相等的值,然后判断该值能否被三等分即可。
代码
#include <bits/stdc++.h> using namespace std; void solve() { int a, b; cin >> a >> b; if (a > b) swap(a, b); int delta = b - a; a -= delta; b -= 2 * delta; cout << (a < 0 or a % 3 ? "NO" : "YES") << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
C - Infinite Fence
题意
给一个数轴上的数染色,要求:
- $r$ 的倍数染为红色
- $b$ 的倍数染为蓝色
- $r,b$ 的公倍数可染任一颜色
- 所有染色的数中连续同色的数应少于 $k$ 个
判断能否按照要求染色。
题解
假设 $r≤b$,只需考虑相邻两个 $b$ 的倍数间最多能放多少个 $r$ 即可。
由裴蜀定理,第一个 $r$ 花费的最短距离为 $gcd(r,b)$, 判断接下来的长度能否放 $k-1$ 个 $r$ 即可。
代码
#include <bits/stdc++.h> using ll = long long; using namespace std; void solve() { ll r, b, k; cin >> r >> b >> k; if (r > b) swap(r, b); b -= __gcd(r, b); cout << ((k - 1) * r < b ? "REBEL" : "OBEY") << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
D - A Game with Traps
题意
你有 $m$ 个士兵,每个士兵最多能承受的陷阱危险等级为 $a_i$,从 $0$ 到 $n+1$ 的数轴上有 $k$ 个陷阱,每个陷阱的位置为 $l_i$,危险等级为 $d_i$,陷阱的解除装置在 $r_i(≥l_i)$ 处,陷阱只会对你的士兵产生影响。
每次你的选择如下:
- 自己移动一个单位距离,花费 $1s$
- 如果你和士兵们在一起,带领他们一起移动一个单位距离,花费 $1s$
- 如果你当前的位置有某个陷阱的解除装置,该陷阱立即解除(不花费时间,士兵的死亡判定优先于陷阱解除)
试判断你最多能带到 $n+1$ 处多少士兵。
题解
每次把士兵们带到需要解除的陷阱前,将该陷阱及途径的陷阱解除后回到原处带领士兵们前往下一个陷阱前,重复此过程至 $n+1$ 。
所以将陷阱按照位置排序,依次解除即可,注意其中有的陷阱可能位置较靠前但解除装置较靠后,所以需要记录当前已解除陷阱中解除装置最靠后的位置。
最后二分寻找最多人数即可。
代码
#include <bits/stdc++.h> using namespace std; int m, n, k, t; vector<int> a, l, r, d; bool can(int x) { int mi = *min_element(a.begin(), a.begin() + x); vector<pair<int, int>> seg; for (int i = 0; i < k; i++) { if (mi < d[i]) { seg.push_back({l[i], r[i]}); } } sort(seg.begin(), seg.end()); int cost = 0; int lastr = 0; for (auto s : seg) { if (s.first <= lastr) { cost += 2 * max(0, s.second - lastr); lastr = max(lastr, s.second); } else { cost += 2 * (s.second - s.first + 1); lastr = s.second; } } return cost + n + 1 <= t; } int main() { cin >> m >> n >> k >> t; a.resize(m); for (int i = 0; i < m; i++) { cin >> a[i]; } sort(a.rbegin(), a.rend()); l.resize(k); r.resize(k); d.resize(k); for (int i = 0; i < k; i++) { cin >> l[i] >> r[i] >> d[i]; } int lf = 0, rt = m + 1; while (rt - lf > 1) { int mid = (lf + rt) / 2; if (can(mid)) lf = mid; else rt = mid; } cout << lf << "\n"; }