A. Exponential Plant
模拟
代码实现
h = int(input()) now, day = 0, 0 while now <= h: now += 1<<day day += 1 print(day)
B. AtCoder Janken 2
模拟
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; int main() { int n; cin >> n; vector<pair<string, int>> user; int t = 0; rep(i, n) { string s; int c; cin >> s >> c; user.emplace_back(s, c); t += c; } sort(user.begin(), user.end()); string ans = user[t%n].first; cout << ans << '\n'; return 0; }
C. AtCoder Magics
其实就是找二维平面上以 最大的点结尾的最长严格上升点列
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; int main() { int n; cin >> n; vector<int> a(n), c(n); rep(i, n) cin >> a[i] >> c[i]; vector<int> is(n); iota(is.begin(), is.end(), 0); sort(is.begin(), is.end(), [&](int i, int j) { return a[i] > a[j]; }); vector<int> ans; for (int i : is) { if (!ans.size() or c[ans.back()] > c[i]) { ans.push_back(i); } } sort(ans.begin(), ans.end()); cout << ans.size() << '\n'; for (int i : ans) cout << i+1 << ' '; return 0; }
E. Remove Pairs
状压dp
记 dp[S]
表示状态为从剩下的卡片集合为 开始的胜负
博弈论的基本性质:
- 一个状态是必败状态,当且仅当它的所有后继都是必胜状态
- 一个状态是必胜状态,当且仅当它至少有一个后继是必败状态
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; int main() { int n; cin >> n; vector<int> a(n), b(n); rep(i, n) cin >> a[i] >> b[i]; int n2 = 1<<n; vector<bool> dp(n2); rep(s, n2) { bool now = false; rep(i, n)rep(j, i) if ((s>>i&1) and (s>>j&1)) { if (a[i] == a[j] or b[i] == b[j]) { if (!dp[s^1<<i^1<<j]) now = true; } } dp[s] = now; } if (dp[n2-1]) puts("Takahashi"); else puts("Aoki"); return 0; }
F. Useless for LIS
可以先求出以每个数结尾的 LIS 的长度
用线段树优化dp可以做到
那么如何判断一个数出现在整个序列的 LIS 里呢?
- 可以先求出以每个数 开始的 LIS 的长度
- 然后判断以 结尾的 LIS 的长度 + 以 开始的 LIS 的长度是否等于整个序列的 LIS 的长度 - 1
代码实现
#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; // Coodinate Compression template<typename T=int> struct CC { bool initialized; vector<T> xs; CC(): initialized(false) {} void add(T x) { xs.push_back(x);} void init() { sort(xs.begin(), xs.end()); xs.erase(unique(xs.begin(),xs.end()),xs.end()); initialized = true; } int operator()(T x) { if (!initialized) init(); return upper_bound(xs.begin(), xs.end(), x) - xs.begin() - 1; } T operator[](int i) { if (!initialized) init(); return xs[i]; } int size() { if (!initialized) init(); return xs.size(); } }; int op(int a, int b) { return max(a, b); } int e() { return 0; } void solve() { int n; cin >> n; vector<int> a(n); rep(i, n) cin >> a[i]; { CC cc; rep(i, n) cc.add(a[i]); rep(i, n) a[i] = cc(a[i]); } auto get = [&]() { vector<int> dp(n); segtree<int, op, e> t(n); rep(i, n) { dp[i] = t.prod(0, a[i])+1; t.set(a[i], dp[i]); } return dp; }; vector<int> dl = get(); rep(i, n) a[i] = n-1-a[i]; reverse(a.begin(), a.end()); vector<int> dr = get(); reverse(dr.begin(), dr.end()); int lis = *max_element(dl.begin(), dl.end()); vector<int> ans; rep(i, n) { if (dl[i]+dr[i]-1 == lis) ans.push_back(i); } cout << ans.size() << '\n'; for (int i : ans) cout << i+1 << ' '; cout << '\n'; } int main() { int t; cin >> t; while (t--) solve(); return 0; }
G. Select Strings
考虑如果 是 的子串,则将点 向点 连一条有向边,特别地,如果 ,直接跳过,可以发现最后得到的图是一个DAG
我们需要求的就是这个图的最大反链,而最大反链 最小链覆盖
对于最小链覆盖是网络流的经典模型:拆点建二分图,原图的最小链覆盖就是 二分图的最大匹配,其中
另外,对于出现 和 相同的情况,可以考虑取这个字符串对应的
代码实现
#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; int main() { int n; cin >> n; vector<string> s; vector<int> a; { vector<string> S(n); rep(i, n) cin >> S[i]; map<string, int> mx; rep(i, n) { int na; cin >> na; mx[S[i]] = max(mx[S[i]], na); } for (auto [ns, na] : mx) { s.push_back(ns); a.push_back(na); } n = s.size(); } int sv = n*2, tv = sv+1; mf_graph<ll> g(tv+1); const ll INF = 1e18; rep(i, n)rep(j, n) if (i != j) { if (s[i].find(s[j]) != string::npos) { g.add_edge(i, n+j, INF); } } rep(i, n) g.add_edge(sv, i, a[i]); rep(i, n) g.add_edge(n+i, tv, a[i]); ll ans = 0; rep(i, n) ans += a[i]; ans -= g.flow(sv, tv); cout << ans << '\n'; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现