The 2024 CCPC Online Contest

https://codeforces.com/gym/105336

1|0B - 军训 II


排序后肯定是最优解,方案数就是能排成有序序列的个数

#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 = 1e9, INF = 1e18; const i64 mod = 998244353; struct mint { i64 x; mint(i64 x = 0) : x(x) {}; mint &operator=(i64 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 = (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, i64 b) { return a ^= b; } i64 val() { x = (x % mod + mod) % mod; return x; } }; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi a(n); for (auto &i: a) cin >> i; ranges::sort(a, greater<>()); int res = 0; for (int cnt = n, sum = accumulate(a.begin(), a.end(), 0); auto i: a) { cnt--, sum -= i; res += cnt * i - sum; } cout << res; vector<mint> fact(n + 1); fact[0] = 1; for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i; mint ret(2 - (a.back() == a.front())); a.push_back(-1); for (int lst = -1, cnt = 0; auto i: a) { if (lst != i) { ret *= fact[cnt], cnt = 1, lst = i; } else { cnt++; } } cout << " " << ret.val(); return 0; }

2|0D - 编码器-解码器


f[i][l][r]表示Si可以匹配T[l,r]的方案数,然后按照题目的意思进行O(N4)的转移就好了。

#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 = 1e9, INF = 1e18; const i64 mod = 998244353; struct mint { i64 x; mint(i64 x = 0) : x(x) {}; mint &operator=(i64 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 = (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, i64 b) { return a ^= b; } i64 val() { x = (x % mod + mod) % mod; return x; } }; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); string s, t; cin >> s >> t; int n = s.size(), m = t.size(); vector f(n, vector(m + 1, vector(m + 1, mint()))); for (int i = 0; i < m; i++) if (s[0] == t[i]) f[0][i][i] = 1; for (int i = 1; i < n; i++) for (int l = 0; l < m; l++) for (int r = l; r < m; r++) { f[i][l][r] = f[i - 1][l][r] * 2; if (l == r) { if (s[i] == t[l]) f[i][l][r] += 1; } else { if (s[i] == t[l]) f[i][l][r] += f[i - 1][l + 1][r]; if (s[i] == t[r]) f[i][l][r] += f[i - 1][l][r - 1]; for (int k = l; k < r; k++) f[i][l][r] += f[i - 1][l][k] * f[i - 1][k + 1][r]; for (int k = l + 1; k < r; k++) if (s[i] == t[k]) f[i][l][r] += f[i - 1][l][k - 1] * f[i - 1][k + 1][r]; } } cout << f[n - 1][0][m - 1].val(); return 0; }

3|0E. 随机过程


最大点数就是使得每一层尽可能的填满。

min(n,26i)

对于期望点数,同一层的点是相互独立的。每层能够出现的点有26i种,对于某一种点,被选到的概率就是126i,那么选不到的概率就是1126i,我们要选择n次,n次都选不到的概率是(1126i)n,所以这个点被选中的概率就是1(1126i)n。这层的点共有26i个,因此总的期望就是26i(1(1126i)n),共m层,所以答案就是

26i[1(1126i)n]

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using ui32 = uint32_t; using i64 = long long; //#define int i64 using vi = vector<int>; using pii = pair<int, int>; const i64 mod = 998244353; struct mint { i64 x; mint(i64 x = 0) : x(x) {} mint &operator=(i64 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; } inline mint &operator^=(int b) { mint w = *this; mint 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; } i64 val() { x = (x % mod + mod) % mod; return x; } }; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; const mint b(26), one(1); mint sum; for (int i = 0, x = 1, t = 26; i <= m; i++) { sum += x; x *= t; if (x > n) x = n, t = 1; } mint res; for (int i = 0; i <= m; i++) { mint t = b ^ i; res += t * (one - ((one - (one / t)) ^ n)); } cout << sum.val() << " " << res.val(); return 0; }

4|0J. 找最小


首先我们可以求出原本的异或和A,B,再求出ci=aibi

此时我们就可以考虑用ci选择一些数去异或,看能否使得答案减小。

我们贪心的从高位开始操作。

如果当前位A,B都是1,能操作就操作。

如果当前位都是0,不需要任何操作。

如果当前位的较大数是1,我们可以考虑操作。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using ui32 = uint32_t; using i64 = long long; //#define int i64 using vi = vector<int>; using pii = pair<int, int>; #define lowbit(x) ( x & -x ) struct Basis { vector<ui32> B; Basis() { B = vector<ui32>(); } void insert(ui32 x) { for (auto b: B) x = min(x, b ^ x); if (x == 0) return; for (auto &b: B) b = min(b, b ^ x); B.push_back(x); return; } ui32 find(ui32 x) { for (auto i: B) { int y = i; while (lowbit(y) != y) y -= lowbit(y); if (x == y) return i; } return 0; } }; void solve() { int n; cin >> n; vector<ui32> a(n), b(n); ui32 A = 0, B = 0; for (auto &i: a) cin >> i, A ^= i; for (auto &i: b) cin >> i, B ^= i; ui32 res = max(A, B); Basis basis; for (int i = 0; i < n; i++) basis.insert(a[i] ^ b[i]); for (ui32 i = (1 << 30); i > 0; i >>= 1) { if (A < B) swap(A, B); if (((A & i) == 0) and ((B & i) == 0)) continue; if (A & i) { ui32 x = basis.find(i); A ^= x, B ^= x; } } res = min(res, max(A, B)); cout << res << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while (T--) solve(); return 0; }

5|0K - 取沙子游戏


这道题目是赛时先写出SG函数,然后找规律发现。

  1. n为奇数先手必胜,因为只要先手拿1后手就只能拿1
  2. kn先手必胜,因为先手可以一步全部拿完。
  3. 剩下的情况通过找规律发现,对于n找到最大的t满足t|nt2的整次幂,那么tk 先手必胜

原因赛时没想出来

#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 = 1e9, INF = 1e18; void solve() { int n, k; cin >> n >> k; if (n & 1) { cout << "Alice\n"; } else if (k >= n) { cout << "Alice\n"; } else { int p = 1; while (n % (p * 2) == 0) p *= 2; if (k < p) cout << "Bob\n"; else cout << "Alice\n"; } } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while (T--) solve(); return 0; }

赛后看了题解,题解总结出来一条规律就是lowbit(n)k先手必胜。

如果lowbit(n)k,先手可以取一个lowbit(n),然后后手一定无法一步取完,这种情况其实和 Nim 博弈很类似。道理上来说我打表找到的规律实际上是殊途同归了

#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 = 1e9, INF = 1e18; #define lowbit(x) ( x & -x ) void solve() { int n, k; cin >> n >> k; if (lowbit(n) > k) cout << "Bob\n"; else cout << "Alice\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while (T--) solve(); return 0; }

6|0L - 网络预选赛


#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 = 1e9, INF = 1e18; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; vector<string> g(n); for (auto &i: g) cin >> i; int res = 0; for (int i = 0; i + 1 < n; i++) for (int j = 0; j + 1 < m; j++) { if (g[i][j] == 'c' and g[i][j + 1] == 'c' and g[i + 1][j] == 'p' and g[i + 1][j + 1] == 'c') res++; } cout << res; return 0; }

__EOF__

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