A. AtCoder Line
判断 是否出现在 和 之间即可
代码实现
n, x, y, z = map(int, input().split()) if x > y: x, y = y, x if x < z < y: print('Yes') else: print('No')
B.Typing
模拟
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; int main() { string s, t; cin >> s >> t; int si = 0; rep(i, t.size()) { if (s[si] == t[i]) { cout << i+1 << ' '; si++; } } return 0; }
C. Standing On The Shoulders
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using ll = long long; int main() { int n; cin >> n; vector<int> a(n), b(n); rep(i, n) cin >> a[i] >> b[i]; int mx = 0; rep(i, n) mx = max(mx, b[i]-a[i]); ll ans = mx; rep(i, n) ans += a[i]; cout << ans << '\n'; return 0; }
D. Permutation Subsequence
可以开一个数组 q
用来记录数 所对应的下标
维护一个大小为 且数值连续的滑动窗口,我们需要快速找到这个窗口中的每个数所对应的下标数组的最大值和最小值,这个可以用 std::set
的 begin()
和 rbegin()
实现
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; int main() { int n, k; cin >> n >> k; vector<int> p(n); rep(i, n) cin >> p[i]; rep(i, n) p[i]--; vector<int> q(n); rep(i, n) q[p[i]] = i; int ans = n; set<int> st; rep(i, n) { st.insert(q[i]); if (st.size() > k) st.erase(q[i-k]); if (st.size() == k) { int now = *st.rbegin() - *st.begin(); ans = min(ans, now); } } cout << ans << '\n'; return 0; }
E. Clique Connect
注意到每个集合中只需留下连通的 条边即可
然后按 排序后,再跑 Kruskal 即可
代码实现
#include <bits/stdc++.h> #if __has_include(<atcoder/all>) #include <atcoder/all> using namespace atcoder; #endif #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using ll = long long; using E = tuple<int, int, int>; int main() { int n, m; cin >> n >> m; vector<E> es; rep(i, m) { int k, c; cin >> k >> c; vector<int> a(k); rep(j, k) cin >> a[j]; rep(j, k) a[j]--; rep(j, k-1) { es.emplace_back(c, a[j], a[j+1]); } } sort(es.begin(), es.end()); dsu uf(n); ll ans = 0; for (auto [c, a, b] : es) { if (uf.same(a, b)) continue; uf.merge(a, b); ans += c; } if (uf.size(0) != n) ans = -1; cout << ans << '\n'; return 0; }
F. Estimate Order
根据限制条件,我们可以向点 到点 加一条边权为 的有向边,同时向点 到点 加一条边权为 的有向边,于是就会形成若干个带权的连通分量
对于一个连通分量,可以用二进制数来表示,那么我们将所有的二进制数做合适的移动再将它们按位或起来就能实现 个位上全为 1
考虑状压dp
假设所有连通块对应的二进制数为
记 dp[i][S]
表示加上 后能变成二进制数 吗
枚举连通块 ,在其他连通块的所有可能的合法组合中如果不止一种嵌入这个连通块的方案的话,那么这个连通块内的人的排名不能唯一确定
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using P = pair<int, int>; int pc(int x) { return __builtin_popcount(x); } int main() { int n, m; cin >> n >> m; vector<vector<P>> g(n); rep(i, m) { int a, b, c; cin >> a >> b >> c; --a; --b; g[a].emplace_back(b, -c); g[b].emplace_back(a, c); } vector<bool> used(n); vector<int> idx(n); vector<vector<int>> vs; vector<int> xs; rep(i, n) if (!used[i]) { auto dfs = [&](auto& f, int v) -> void { vs.back().push_back(v); used[v] = true; for (auto [u, c] : g[v]) { if (used[u]) continue; idx[u] = idx[v]+c; f(f, u); } }; vs.push_back(vector<int>()); dfs(dfs, i); int mn = 0; for (int v : vs.back()) mn = min(mn, idx[v]); for (int v : vs.back()) idx[v] -= mn; int x = 0; for (int v : vs.back()) x |= 1<<idx[v]; xs.push_back(x); } m = xs.size(); int n2 = 1<<n; vector<int> ans(n, -1); rep(k, m) { vector<bool> dp(n2); dp[0] = true; int num = 0; rep(i, m) if (i != k) { rep(s, n2) if (pc(s) == num and dp[s]) { int x = xs[i]; while (x < n2) { if ((s&x) == 0) dp[s|x] = true; x <<= 1; } } num += vs[i].size(); } int x = xs[k], cnt = 0; int offset = 0, i = 0; while (x < n2) { if (dp[(n2-1)^x]) offset = i, cnt++; x <<= 1; i++; } if (cnt == 1) { for (int v : vs[k]) ans[v] = offset+idx[v]+1; } } rep(i, n) cout << ans[i] << ' '; return 0; }
G. Socks 3
记
待求期望等价于求 取 次袜子且还没结束的概率
取 次袜子且还没结束的方案数
记 表示取 次袜子且还没结束的方案数
那么 就是从每种颜色的袜子中取 个或 个总共取 个的方案数,这是不是很像01背包?
写成生成函数的形式就是 ,这个式子可以用分治NTT计算
另外在选取的袜子之间还需要进行排序,所以要再乘上
总的时间复杂度为
代码实现
#include <bits/stdc++.h> #if __has_include(<atcoder/all>) #include <atcoder/all> using namespace atcoder; #endif #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using mint = modint998244353; using fps = vector<mint>; int main() { int n; cin >> n; vector<int> a(n); rep(i, n) cin >> a[i]; int s = 0; rep(i, n) s += a[i]; queue<fps> q; rep(i, n) { fps f = {1, a[i]}; q.push(f); } while (q.size() > 1) { fps a = q.front(); q.pop(); fps b = q.front(); q.pop(); q.push(convolution(a, b)); } fps f = q.front(); mint ans, co = 1; rep(k, n+1) { ans += f[k]*co; co /= s-k; co *= k+1; } cout << ans.val() << '\n'; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具