The 2024 ICPC Asia East Continent Online Contest (II)

1|0A. Gambling on Choosing Regionals


最差情况就是,强队都和你去一起。因此赛站越小,排名也一定越小。

然后只要动态实现出每个学校最强的若干只队伍就好了。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = vector<int>; using pii = pair<int, int>; const int inf = INT_MAX / 2; #define lowbit(x) (x & -x) struct BinaryIndexedTree { int n, sum; vi b; BinaryIndexedTree(int n) : n(n), b(n + 1) { sum = 0; } void modify(int i, int y) { sum += y; for (; i <= n; i += lowbit(i)) b[i] += y; return; } int calc(int i) { int ans = 0; for (; i; i -= lowbit(i)) ans += b[i]; return ans; } int upper(int x) { return sum - calc(x); } }; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, k; cin >> n >> k; int c = inf; for (int i = 1, x; i <= k; i++) cin >> x, c = min(c, x); vector<pair<int, string>> team(n); vi hw; for (auto &[w, u]: team) cin >> w >> u, hw.push_back(w); sort(hw.begin(), hw.end()); hw.resize(unique(hw.begin(), hw.end()) - hw.begin()); for (auto &[w, u]: team) w = lower_bound(hw.begin(), hw.end(), w) - hw.begin() + 1; map<string, vector<pii>> cnt; for (int i = 0; i < n; i++) cnt[team[i].second].emplace_back(team[i].first, i); BinaryIndexedTree bit(hw.size()); for (auto &[u, t]: cnt) { sort(t.begin(), t.end(), greater<>()); for (int i = 0, N = min(c, (int) t.size()); i < N; i++) bit.modify(t[i].first, 1); } vi res(n); for (auto &[u, t]: cnt) { for (int i = 0, N = min(c, (int) t.size()); i < N; i++) bit.modify(t[i].first, -1); for (int i = 0; i < t.size(); i++) { res[t[i].second] = bit.upper(t[i].first) + min(i, c - 1) + 1; } for (int i = 0, N = min(c, (int) t.size()); i < N; i++) bit.modify(t[i].first, 1); } for (int i: res) cout << i << "\n"; return 0; }

2|0E. Escape


你和机器人都不能停留在原地。其次d的限制并不是步数,而是移动半径。

假设你和机器人都可以停留在原地。那么我们可以预处理机器人到达某个点x的最早时间t[x]

如果你到达x的最早时间为f,则必须要保证f<t[x]。而对于t,可以直接用多源bfs实现。

我们考虑不能停留的情况,机器人不能提前到达你的路上截停你,而是要在你路径上的某个点反复到达离开。如果f<t[x]则无所谓。如果f>t[x],则必须有(ft[x])mod2=0。然后要知道,机器人不唯一,到达某个点的路径也不唯一。因此我们要分奇偶求出到达每个点的最早时间。同理,在计算你的到达时间时也要分奇偶考虑。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = vector<int>; using pii = pair<int, int>; const i32 inf = INT_MAX / 2; const int mod = 998244353; void solve() { int n, m, d; cin >> n >> m >> d; vector<vi> e(n + 1); for (int i = 1, x, y; i <= m; i++) { cin >> x >> y; e[x].push_back(y), e[y].push_back(x); } int k; cin >> k; vector t(2, vi(n + 1, inf)); queue<pii> q; for (int i = 1, x; i <= k; i++) { cin >> x; t[0][x] = 0, q.emplace(x, 0); } vector vis(2, vi(n + 1)); while (not q.empty()) { auto [x, tx] = q.front(); q.pop(); if (vis[tx & 1][x]) continue; vis[tx & 1][x] = 1; if (tx == d) continue; for (int ty = tx + 1; auto y: e[x]) { if (vis[ty & 1][y]) continue; if (t[ty & 1][y] <= ty) continue; t[ty & 1][y] = ty, q.emplace(y, ty); } } q.emplace(1, 0); vis = vector(2, vi(n + 1)); vector f(2, vi(n + 1, inf)); vector lst(2, vi(n + 1, -1)); f[0][1] = 0; while (not q.empty()) { auto [x, fx] = q.front(); q.pop(); if (vis[fx & 1][x]) continue; vis[fx & 1][x] = 1; for (int fy = fx + 1; auto y: e[x]) { if (vis[fy & 1][y]) continue; if (t[fy & 1][y] <= fy) continue; if (f[fy & 1][y] <= fy) continue; f[fy & 1][y] = fy, lst[fy & 1][y] = x; q.emplace(y, fy); } } int ret = min(f[0][n], f[1][n]); if (ret == inf) { cout << "-1\n"; return; } cout << ret << "\n"; vi p; for (int x = n, y = ret & 1; x != -1; x = lst[y][x], y ^= 1) p.push_back(x); ranges::reverse(p); for (auto i: p) cout << i << " "; cout << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while (T--) solve(); return 0; }

3|0F. Tourist


签到

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; i64 cnt = 1500; for (int i = 1, x; i <= n; i++) { cin >> x, cnt += x; if (cnt >= 4000) { cout << i << "\n"; return 0; } } cout << -1; return 0; }

4|0G. Game


平局的状态不影响结果。因此我们可以记Alice 获胜的概率是Pa=a0a0+a1,Bob 获胜的概率是Pb=a1a0+a1

我们可以利用一种类似更相减损术的方法求解。但是复杂度太高了。我们考虑归纳一下。

对于当前的状态(x,y),有以下三种情况

  1. x=y,此时Alice获胜的概率是Pa
  2. x<y,此时Alice必须连续至少赢得d=yxx 局,才有机会获胜,因此可以递归计算(x,ydy)
  3. x>y,此时Bob必须连续至少赢得d=xyy 局,才有机会获胜,因此可以递归计算(xdy,y)

这样的话,复杂度就和辗转相除法一样是O(logn)

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = vector<int>; using pii = pair<int, int>; const i32 inf = INT_MAX / 2; const int mod = 998244353; struct mint { i64 x; mint(int x = 0) : x(x) {} int val() const { return (x % mod + mod) % mod; } mint &operator=(int o) { return x = o, *this; } mint &operator+=(mint o) { return (x += o.x) >= mod && (x -= mod), *this; } mint &operator-=(mint o) { return (x -= o.x) < 0 && (x += mod), *this; } mint &operator*=(mint o) { return x = (i64) x * o.x % mod, *this; } mint &operator^=(int b) { mint w = *this, ret(1); for (; b; b >>= 1, w *= w) if (b & 1) ret *= w; return x = ret.x, *this; } mint &operator/=(mint o) { return *this *= (o ^= (mod - 2)); } friend mint operator+(mint a, mint b) { return a += b; } friend mint operator-(mint a, mint b) { return a -= b; } friend mint operator*(mint a, mint b) { return a *= b; } friend mint operator/(mint a, mint b) { return a /= b; } friend mint operator^(mint a, int b) { return a ^= b; } }; void solve() { int x, y, _; cin >> x >> y; mint a, b; cin >> a.x >> b.x >> _; mint pa = a / (a + b), pb = b / (a + b); auto calc = [pa, pb](auto &&calc, int x, int y, mint p) -> mint { if (x == y) return p * pa; if (x < y) { int d = (y - x + x - 1) / x; return calc(calc, x, y - d * x, p * (pa ^ d)); } else { int d = (x - y + y - 1) / y; return p * (1 - (pb ^ d)) + calc(calc, x - d * y, y, p * (pb ^ d)); } }; cout << calc(calc, x, y, mint(1)).val() << "\n"; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while (T--) solve(); return 0; }

5|0I. Strange Binary


4的倍数无解,然后我们考虑先构造奇数,然后在加1即可

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = vector<int>; using pii = pair<int, int>; const i32 inf = INT_MAX / 2; const int mod = 998244353; void solve() { int n; cin >> n; if (n % 4 == 0) { cout << "NO\n"; return; } bool ok = false; if (n % 2 == 0) { ok = true; n--; } vi a(32, -1); a[31] = 1, n /= 2; for (int i = 0; i < 31; i++) if (n >> i & 1) a[i] = 1; if (ok) a[0] = 0; cout << "YES"; for (int i = 0; i < 32; i++) cout << " \n"[i % 8 == 0] << a[i]; cout << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while (T--) solve(); return 0; }

6|0J. Stacking of Goods


可以证明按照ciwi排序一定最优,剩下的贪心就好了。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = vector<int>; using pii = pair<int, int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi w(n), c(n); int res = 0; for (int i = 0, v; i < n; i++) { cin >> w[i] >> v >> c[i]; res += v; } vi p(n); iota(p.begin(), p.end(), 0); sort(p.begin(), p.end(), [&](const int &x, const int &y) -> bool { return -c[y] * w[x] > -c[x] * w[y]; }); vi W(n); for (int i = n - 2; i >= 0; i--) W[p[i]] = W[p[i + 1]] + w[p[i + 1]]; for (auto i: p) res -= c[i] * W[i]; cout << res; return 0; }

7|0L. 502 Bad Gateway


其实可以猜到存在一个阈值x,满足小于等于x时,不做额外的操作,大于x时不断的随机。

对于小于等于x的部分,期望次数就是

1T+2T+3TxT

然后我们考虑大于x的情况,大于的情况总共有Tx种,每一种的概率都是1T。对于随机,随机到小于等于x的概率为xT,这就是一个简单的几何分布,因此期望就是Tx。当我们随机到小于等于x的情况下,还需要操作的期望是1x+2x+3x+xx。因此大于x部分的期望就是

TxT(Tx+1x+2x+3x+xx)

因此总的期望此时就是

Ex=x2(x+1)+(Tx)[2T+x(x+1)]2Tx

这个式子很遗憾不满足单调性。但是通过打表发现,当T1,2,3时,x的取值为

1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using i128 = __int128; #define int i64 using vi = vector<int>; using pii = pair<int, int>; const int inf = LLONG_MAX / 2; using ldb = long double; const ldb eps = 1e-12; i128 gcd(i128 a, i128 b) { return b ? gcd(b, a % b) : a; } ostream &operator<<(ostream &os, i128 x){ string s; while(x > 0) s += char(x % 10 + '0'), x /= 10; reverse(s.begin(), s.end()); os << s; return os; } struct Z { i128 x, y; Z() {} void norm(){ i128 d = gcd(x, y); x /= d, y /= d; } bool operator<(const Z &b) const{ return x * b.y < b.x * y; } Z &operator=(Z b) { x = b.x, y = b.y; return *this; } }; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while(T --){ int n; cin >> n; auto calc =[&](int x ) -> Z{ Z ans; ans.x = (i128)x * x *(x + 1) + (i128)(n - x) * ((i128)n * 2 + x * (x + 1)); ans.y = (i128)n * x * 2; ans.norm(); return ans; }; int l = 1 , r = n , ret = -1; while(l <= r){ int mid = (l + r) / 2; if(mid * (mid + 1) / 2 >= n) ret = mid, r = mid - 1; else l = mid + 1; } auto res = calc(ret); cout << res.x << " " << res.y << "\n"; } return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18442957.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
历史上的今天:
2023-10-01 The 2022 ICPC Asia Shenyang Regional Contest
2023-10-01 Codeforces Round 811 (Div. 3)
2022-10-01 女神训练赛 Round01
点击右上角即可分享
微信分享提示