structNode { string s, t; }; voidsolve(){ int n = read(); vector<Node> a(n); for (auto &[s, t] : a) { getline(cin, s); int m = s.size(); for (int i = 0; i < m; i++) { if ('A' <= s[i] and s[i] <= 'Z') { t = s.substr(i); break; } } }
std::sort(a.begin(), a.end(), [&](Node a, Node b) { return a.t < b.t; });
voidsolve(){ int n = read(); int m = read(); int x = read(); int y = read(); vector<int> a(n); for (auto &x : a) x = read(); std::ranges::sort(a); vector<int> b(m); for (auto &x : b) x = read(); std::ranges::sort(b);
auto judge = [&](int lim) { // [1, lim] vector t(n, x); for (int i = 0; i < lim; i++) { t[i] = y; }
int p = 0; for (auto x : b) { if (t[p] > 0and a[p] >= x) { t[p]--; } else { while (p < n and (a[p] < x or !t[p])) p++; if (p >= n) return0; t[p]--; } } return1; };
int ans = -1; for (int L = 0, R = n; L <= R; ) { int mid = L + R >> 1; if (judge(mid)) { ans = mid, L = mid + 1; } else { R = mid - 1; } }
if (ans == -1) { cout << "impossible\n"; } else { cout << ans << '\n'; } }
D - Dutch Democracy
给定 n 个政党及其席位数量,有多少个子集满足以下条件:
子集的累计席位数量大于总席位数量的一半,并且
放弃任何一个政党都会使累计席位数量小于等于总席位数量的一半?
$1 \le n \le 60$ $1 \le p \le 10,000$, the number of seats each party has.
将条件 2 转化为删除最小值后,子集的和 小于等于 全集的和 的一半
$O(n)$ 枚举最小值 $x$,问题转化成求子集数量,使得子集和 + x > tot / 2, 子集和 < tot / 2,$O(np)$ 01 背包求解,总复杂度 $O(n^2p)$
更进一步地,直接从大到小排序,每次用来更新状态的必然是最小的,时间复杂度 $O(n\log n + np)$
voidsolve(){ int n = read(); vector<int> a(n); for (auto &x : a) x = read(); std::sort(a.rbegin(), a.rend()); int sum = std::accumulate(a.begin(), a.end(), 0ll);
int half = sum / 2; int ans = 0; vector<int> f(1e6);
for (auto x : a) { for (int j = half; j >= 0; j--) { f[j + x] += f[j]; if (j + x > half) ans += f[j]; }
f[x]++; if (x > half) ans++; } cout << ans << '\n'; }
E - Evolving Etymology
Code >folded
1
K - Kruidnoten
在无向图中,其中一些点有 $p_i$ 的概率成为特殊点,每个点之间的概率独立计算,问在至少经过一个特殊点的情况下从 1 到 n 的期望最短路径是多少
longdouble ans = 0, pre = 1; for (auto [dis, id, p] : a) { ans += dis * pre * p; pre *= (1.0 - p); } cout << fixed << setprecision(10) << ans << '\n'; }