T1:Nine
当 且 时,说明 和 相邻
代码实现
a, b = map(int, input().split()) if a+1 == b and a%3 != 0: print('Yes') else: print('No')
T2:Rotate
模拟
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using P = pair<int, int>; int main() { int n; cin >> n; vector<string> a(n); rep(i, n) cin >> a[i]; vector<P> ps; rep(i, n-1) ps.emplace_back(0, i); rep(i, n-1) ps.emplace_back(i, n-1); rep(i, n-1) ps.emplace_back(n-1, n-1-i); rep(i, n-1) ps.emplace_back(n-1-i, 0); auto b = a; int m = ps.size(); rep(mi, m) { auto [i, j] = ps[mi]; auto [ni, nj] = ps[(mi+1)%m]; b[ni][nj] = a[i][j]; } rep(i, n) cout << b[i] << '\n'; return 0; }
T3:Medicine
对于第 天所吃的药的总和为 ,我们可以将相同的 划分为一组
比如样例1:
1: 19 2: 10 3: 5 4: 5 5: 3 6: 3 7: 0
可以将 划分为一组, 划分到一组,其他数单独为一组
考虑对序列 按 的大小进行升序排序
可以发现,如果 ,那么 一定在新的组中,我们只需考虑同一个 第一次出现的位置即可
于是,我们可以仅对序列 按 的大小进行升序排序
在我们扫描序列 时,可以通过当前组的 减去 就能得到新的一组的
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using ll = long long; using P = pair<int, int>; int main() { int n, k; cin >> n >> k; vector<P> ps; ll tot = 0; rep(i, n) { int a, b; cin >> a >> b; ps.emplace_back(a, b); tot += b; } if (tot <= k) { puts("1"); return 0; } sort(ps.begin(), ps.end()); for (auto [a, b] : ps) { tot -= b; if (tot <= k) { cout << a+1 << '\n'; return 0; } } return 0; }
也可以用 std::map<int, int>
来实现
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using ll = long long; using P = pair<int, int>; int main() { int n, k; cin >> n >> k; map<int, ll> mp; ll tot = 0; rep(i, n) { int a, b; cin >> a >> b; mp[a] += b; tot += b; } if (tot <= k) { puts("1"); return 0; } for (auto [a, b] : mp) { tot -= b; if (tot <= k) { cout << a+1 << '\n'; return 0; } } return 0; }
T4:Add One Edge
跑两遍 bfs 分别求出从点 和点 开始的最长路
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using ll = long long; using P = pair<int, int>; int main() { int n1, n2, m; cin >> n1 >> n2 >> m; int n = n1+n2; vector<vector<int>> to(n); rep(i, m) { int a, b; cin >> a >> b; --a; --b; to[a].push_back(b); to[b].push_back(a); } vector<int> d1, dt; auto bfs = [&](int sv) { const int INF = 1001001001; vector<int> dist(n, INF); queue<int> q; q.push(sv); dist[sv] = 0; while (q.size()) { int v = q.front(); q.pop(); for (int u : to[v]) { if (dist[u] != INF) continue; dist[u] = dist[v]+1; q.push(u); } } return dist; }; d1 = bfs(0); dt = bfs(n-1); int ans = 1; { int mx = 0; rep(i, n1) mx = max(mx, d1[i]); ans += mx; } { int mx = 0; rep(i, n2) mx = max(mx, dt[n1+i]); ans += mx; } cout << ans << '\n'; return 0; }
T5:Family and Insurance
注意到,假设点 的父节点为 ,同时 的保险补偿对象是他的子孙 代人,那么点 除了保险对象以外,还需将保险补偿交给他的子孙 代人,所以要将 挂在点 上
记 dp[v]
表示点 的保险补偿对象是他的后几代人
然后自顶向下转移即可
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; int main() { int n, m; cin >> n >> m; vector<vector<int>> to(n); for (int i = 1; i < n; ++i) { int p; cin >> p; --p; to[p].push_back(i); } vector<int> d(n, -1); rep(i, m) { int x, y; cin >> x >> y; --x; d[x] = max(d[x], y); } auto dfs = [&](auto f, int v) -> void { for (int u : to[v]) { d[u] = max(d[u], d[v]-1); f(f, u); } }; dfs(dfs, 0); int ans = 0; rep(i, n) if (d[i] != -1) ans++; cout << ans << '\n'; return 0; }
T6:Box in Box
首先,我们可以对 排序使得
然后接下来就是扫描线的工作了
具体地,我们可以先将 按 的大小做升序排序,再枚举 ,调查之前有没有 满足 且 ,此时我们可以不管 ,那么这个问题就是个二维偏序问题:我们需要对 进行离散化并作为 坐标,将 作为 坐标,然后调查当前 坐标左边的 坐标的最小值是否小于当前的 坐标即可,可以用线段树来维护
代码实现
#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 P = pair<int, int>; // 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(); } }; const int INF = 1001001001; int op(int a, int b) { return min(a, b); } int e() { return INF; } int main() { int n; cin >> n; map<int, vector<P>> ps; CC bs; rep(i, n) { vector<int> a(3); rep(j, 3) cin >> a[j]; sort(a.begin(), a.end()); ps[a[0]].emplace_back(a[1], a[2]); bs.add(a[1]); } segtree<int, op, e> t(bs.size()); for (auto [a, bc] : ps) { for (auto [b, c] : bc) { b = bs(b); if (t.prod(0, b) < c) { puts("Yes"); return 0; } } for (auto [b, c] : bc) { b = bs(b); t.set(b, min(c, t.get(b))); } } puts("No"); return 0; }
T7: Ban Permutation
注意到这里的 比较小,所以可以考虑容斥
只需遍历 的所有子集,将每个子集对应的以下的值加起来即可:
- 对于 中的每个 都满足 的排列 的个数
下面考虑子集 中的每个 都满足 的排列 的个数:
记 dp[i][j][s]
表示在 的前 项中先确定了 个数,其中介于 之间的以 进制表示的整数集合为
代码实现
#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 ll = long long; using P = pair<int, int>; int main() { int n, x; cin >> n >> x; --x; int w = x*2, w2 = 1<<w; vector dp(1, vector<mint>(w2)); dp[0][(1<<x)-1] = 1; rep(i, n) { vector p(i+2, vector<mint>(w2)); swap(dp, p); rep(j, i+1)rep(s, w2) { mint now = p[j][s]; if (now == 0) continue; dp[j][s>>1] += now; rep(k, w+1) if (~s>>k&1) { dp[j+1][(s|1<<k)>>1] += now; } } } vector<mint> fact(n+1, 1); rep(i, n) fact[i+1] = fact[i]*(i+1); mint ans; rep(j, n+1)rep(s, w2) { mint now = dp[j][s]; if (now == 0) continue; if (s >= (1<<x)) continue; ans += now*fact[n-j]*mint(-1).pow(j); } 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工具