SMU winter 2025 Personal Round 2
SMU winter 2025 Personal Round 2
A. Ichihime and Triangle
思路
\(a, b, c, d\) 单调递增,所以 \(x, y, z\) 也会单调递增。这时只需要满足 \(x + y > z\) 就行了。
我们把 \(x, y\) 取最大值:\(x = b\), \(y = c\);\(z\) 取最小值:\(z = c\)。就是最有可能实现的方案。
这时我们发现 \(x + y > z\),说明一定能实现。所以直接输出 \(b,c, c\) 即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int a, b, c, d; cin >> a >> b >> c >> d; cout << b << " " << c << " " << c << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
B - Kana and Dragon Quest game
思路
对第一种操作,当 \(x > 20\) 时,该操作会一直减小 \(x\)。
所以当 \(x > 20\) 时,我们可以一直执行第一种操作,然后再执行第二种操作,这样能尽可能的减少 \(x\)。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int x, n, m; cin >> x >> n >> m; while (x > 20 && n) { n --; x = x / 2 + 10; } cout << (x > m * 10 ? "NO\n" : "YES\n"); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
C - Linova and Kingdom
思路
建立好树,令1号节点的深度是1,然后往下走,当遍历到的点是叶子节点时,该点的贡献是该点到1号节点的距离(\(deep-1\)),当该点不是叶子节点时该点的贡献是\(deep-cnt\)(\(cnt\)为算上自己和自己所有子子孙孙且都认为是工业节点的数量)。
这样得到的数组按贡献降序排序,并将前\(k\)个贡献累加即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, k; cin >> n >> k; vector g(n + 1, vector<int>()); for (int i = 1; i < n; i ++) { int u, v; cin >> u >> v; g[u].emplace_back(v); g[v].emplace_back(u); } vector<int> dep(n + 1), has(n + 1); auto dfs = [&](auto && self, int u, int fa)->void{ dep[u] = dep[fa] + 1; has[u] = 1; for (auto &v : g[u]) { if (v == fa) continue; self(self, v, u); has[u] += has[v]; } }; dfs(dfs, 1, 0); vector<int> a(n + 1); iota(a.begin(), a.end(), 0); sort(a.begin() + 1, a.end(), [&](auto x, auto y) { return dep[x] - has[x] > dep[y] - has[y]; }); i64 ans = 0; for (int i = 1; i <= k; i ++) { ans += dep[a[i]] - has[a[i]]; } cout << ans << "\n"; return 0; }
D - Xenia and Colorful Gems
思路
先枚举其中一个,然后二分找到距离该点较近的几个数,得到两个数后,便可以得知第三个数的范围,在此基础上再去进行二分,然后枚举计算最小值即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n[3] {}; for (int i : {0, 1, 2}) { cin >> n[i]; } vector has(3, vector<int>()); for (int i : {0, 1, 2}) { has[i].resize(n[i]); for (auto &x : has[i]) { cin >> x; } sort(has[i].begin(), has[i].end()); } i64 ans = LLONG_MAX; auto ck = [&](int idx)->void{ for (auto &x : has[idx]) { int ny = lower_bound(has[(idx + 1) % 3].begin(), has[(idx + 1) % 3].end(), x) - has[(idx + 1) % 3].begin(); for (int i = max(0, ny - 5); i < min(n[(idx + 1) % 3], ny + 6); i ++) { i64 y = has[(idx + 1) % 3][i]; int nz = lower_bound(has[(idx + 2) % 3].begin(), has[(idx + 2) % 3].end(), (x + y) / 2) - has[(idx + 2) % 3].begin(); for (int j = max(0, nz - 5); j < min(n[(idx + 2) % 3], nz + 6); j ++) { i64 z = has[(idx + 2) % 3][j]; ans = min(ans, (x - y) * (x - y) + (x - z) * (x - z) + (y - z) * (y - z)); } } } }; ck(0); ck(1); ck(2); cout << ans << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
E - Kaavi and Magic Spell
思路
动态规划,定义状态 \(dp[i][j]\) 表示使用 \(S\) 的前 \(j-i+1\) 个字符构造的字符串恰好覆盖 \(T\) 的第 \(i\) 到 \(j\) 位时的方案数。初始时,若 \(S\) 的第一个字符与 \(T\) 的第 \(k\) 位匹配(或 \(k > m\)),则 \(dp[k][k] = 2\)(两种操作方式)。
对于长度为 \(len\) 的子问题,若当前字符 \(s[len]\) 添加到前端且与 \(T[i]\) 匹配(或 \(i > m\)),则从 \(dp[i+1][j]\) 转移;若添加到后端且与 \(T[j]\) 匹配(或 \(j > m\)),则从 \(dp[i][j-1]\) 转移。最终答案为所有满足 \(1 \leq i \leq j \leq n\) 且 \(j \geq m\) 的 \(dp[1][j]\) 之和。时间复杂度为 \(O(n^2)\),空间复杂度 \(O(n^2)\)。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; //------取模机------// using i64 = long long; template<class T> constexpr T power(T a, i64 b) { T res {1}; for (; b; b /= 2, a *= a) { if (b % 2) { res *= a; } } return res; } // 快速幂 constexpr i64 mul(i64 a, i64 b, i64 p) { i64 res = a * b - i64(1.L * a * b / p) * p; res %= p; if (res < 0) { res += p; } return res; } // 取模乘 template<i64 P> struct MInt { i64 x; constexpr MInt() : x {0} {} constexpr MInt(i64 x) : x {norm(x % getMod())} {} static i64 Mod; constexpr static i64 getMod() { if (P > 0) { return P; } else { return Mod; } } constexpr static void setMod(i64 Mod_) { Mod = Mod_; }//只有P<=0, setMod才生效 constexpr i64 norm(i64 x) const { if (x < 0) { x += getMod(); } if (x >= getMod()) { x -= getMod(); } return x; } constexpr i64 val() const { return x; } constexpr MInt operator-() const { MInt res; res.x = norm(getMod() - x); return res; } constexpr MInt inv() const { return power(*this, getMod() - 2); } constexpr MInt &operator*=(MInt rhs) & { if (getMod() < (1ULL << 31)) { x = x * rhs.x % int(getMod()); } else { x = mul(x, rhs.x, getMod()); } return *this; } constexpr MInt &operator+=(MInt rhs) & { x = norm(x + rhs.x); return *this; } constexpr MInt &operator-=(MInt rhs) & { x = norm(x - rhs.x); return *this; } constexpr MInt &operator/=(MInt rhs) & { return *this *= rhs.inv(); } friend constexpr MInt operator*(MInt lhs, MInt rhs) { MInt res = lhs; res *= rhs; return res; } friend constexpr MInt operator+(MInt lhs, MInt rhs) { MInt res = lhs; res += rhs; return res; } friend constexpr MInt operator-(MInt lhs, MInt rhs) { MInt res = lhs; res -= rhs; return res; } friend constexpr MInt operator/(MInt lhs, MInt rhs) { MInt res = lhs; res /= rhs; return res; } friend constexpr std::istream &operator>>(std::istream &is, MInt &a) { i64 v; is >> v; a = MInt(v); return is; } friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) { return os << a.val(); } friend constexpr bool operator==(MInt lhs, MInt rhs) { return lhs.val() == rhs.val(); } friend constexpr bool operator!=(MInt lhs, MInt rhs) { return lhs.val() != rhs.val(); } friend constexpr bool operator<(MInt lhs, MInt rhs) { return lhs.val() < rhs.val(); } }; constexpr int MOD[] = {998244353, 1000000007}; using Z = MInt<MOD[0]>; //------取模机------// int main() { ios::sync_with_stdio(false); cin.tie(nullptr); string s, t; cin >> s >> t; int n = s.size(), m = t.size(); vector dp(n + 1, vector<Z>(n + 1)); s = " " + s, t = " " + t; for (int i = 1; i <= n; i ++) { if (i > m || s[1] == t[i]) { dp[i][i] = 2; } } for (int len = 2; len <= n; len ++) { for (int i = 1; i + len - 1 <= n; i ++) { int j = i + len - 1; if (i > m || s[len] == t[i]) { dp[i][j] += dp[i + 1][j]; } if (j > m || s[len] == t[j]) { dp[i][j] += dp[i][j - 1]; } } } Z ans = 0; for (int i = m; i <= n; i ++) { ans += dp[1][i]; } cout << ans << "\n"; return 0; }
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18706506
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步