2025寒假天梯赛训练2
2025寒假天梯赛训练2
L1-1 谢谢卡尔!
思路
谢谢卡尔!(>_<)/
代码
谢谢卡尔!\(>_<)/
L1-2 现在是,幻想时间!
思路
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, T; cin >> N >> T; cout << fixed << setprecision(3) << 1.0 * N / T << "\n"; return 0; }
L1-3 你是来陪可莉炸鱼的吗?
思路
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; int ans = 0; while (n--) { int x; cin >> x; if (x < 100) { ans += 1; } else if (x < 200) { ans += 2; } else if (x < 300) { ans += 5; } else if (x < 400) { ans += 10; } else { ans += 15; } } cout << ans << "\n"; return 0; }
L1-4 扫雷游戏
思路
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<string> s(n); for (auto &i : s) { cin >> i; } const int u[] = {1, 1, 1, -1, -1, -1, 0, 0}; const int v[] = {1, 0, -1, 1, 0, -1, 1, -1}; for (int i = 0; i < n; i ++) { for (int j = 0; j < m; j ++) { int res = 0; for (int k = 0; k < 8; k ++) { int x = i + u[k], y = j + v[k]; if (x >= 0 && x < n && y >= 0 && y < m) { res += s[x][y] == '*'; } } if (s[i][j] == '*') { cout << "*"; } else if (res == 0) { cout << "."; } else { cout << res; } if (j == m - 1) { cout << "\n"; } } } return 0; }
L1-5 史莱姆
思路
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; string s; cin >> s; string ans = ""; for (int i = 0; i < n; i ++) { if (i == 0 || s[i] != s[i - 1]) { ans += s[i]; } } cout << ans.size() << "\n"; cout << ans << "\n"; return 0; }
L1-6 加密通信
思路
注意减法取模时可能有 \(n \le m\) ,所以需要乘以一个 \(m\)。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m ; string s; cin >> s; vector<int> a(26); for (int i = 0; i < 26; i ++) { cin >> a[i]; } for (int i = 0; i < n; i ++) { cout << a[s[(i - m + n * m) % n] - 'a']; } return 0; }
L1-7 字符操作
思路
记录该字符串是否处于前后缀交换期间,若是,则对于 \(1\) 操作的位置需要右移一半。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; string s; cin >> s; int q; cin >> q; bool ok = 0; while (q--) { int op, a, b; cin >> op >> a >> b; a--, b--; if (op == 1) { if (!ok) { swap(s[a], s[b]); } else { swap(s[(a + n) % (2 * n)], s[(b + n) % (2 * n)]); } } else { ok ^= 1; } } if (ok) { s = s.substr(n) + s.substr(0, n); } cout << s << "\n"; return 0; }
L1-8 vivo50!
思路
模拟。
代码
#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<pair<double, string>> grade; for (int i = 0; i < n; i ++) { string s; double f1; int f2, f3, gua; cin >> s >> f1 >> f2 >> f3 >> gua; if (!gua) continue; f1 = (f1 * 10) + 50; f2 += 70; f2 = min(f2, 100); grade.emplace_back((f1 + f3) * 0.7 + f2 * 0.3, s); } sort(grade.begin(), grade.end(), [](auto x, auto y) { if (x.first == y.first) return x.second < y.second; return x.first > y.first; }); int rank = 0; cout << fixed << setprecision(1); for (int i = 0; i < grade.size(); i ++) { rank = i + 1; if (rank > k) break; cout << rank << " " << grade[i].second << " " << grade[i].first << "\n"; while (i + 1 < grade.size() && grade[i + 1].first == grade[i].first) { i ++; cout << rank << " " << grade[i].second << " " << grade[i].first << "\n"; } } return 0; }
L2-1 游戏圈
思路
并查集模板。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; struct DSU { vector<int> rank, p; DSU(int n) { rank.assign(n, 0); p.assign(n, 0); iota(p.begin(), p.end(), 0); } void link(int x, int y) { if (x == y) return; if (rank[x] > rank[y]) p[y] = x; else p[x] = y; if (rank[x] == rank[y]) rank[y]++; } int find(int x) { return x == p[x] ? x : (p[x] = find(p[x])); } void merge(int x, int y) { link(find(x), find(y)); } bool same(int x, int y) { return find(x) == find(y); } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, q; cin >> n >> m >> q; DSU dsu(n + 1); while (m--) { int a, b; cin >> a >> b; dsu.merge(a, b); } while (q--) { int a, b; cin >> a >> b; cout << (dsu.same(a, b) ? "yes" : "no") << "\n"; } int res = 0; for (int i = 1; i <= n; i ++) { res += dsu.find(i) == i; } cout << res << "\n"; return 0; }
L2-2 组套题
思路
比较坑的点是,题中并未对最接近
说明,我以为是左右差值越小越接近,实际上是一直先找大的,大的没有了才找小的。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> t(10), has(10); for (int i = 0; i < 10; i ++) { cin >> t[i]; } vector T(10, vector<array<int, 3>>()); for (int i = 1; i <= n; i ++) { int k; cin >> k; while (k--) { char c; int hard, num; cin >> c >> hard >> c >> num; hard --; T[hard].push_back({hard, i, num}); has[hard] ++; } } for (auto &x : T) { reverse(x.begin(), x.end()); } vector<array<int, 3>> ans; auto del = [&](int i, int j)->void{ while (t[i] && has[j]) { ans.push_back(T[j].back()); T[j].pop_back(); t[i] -- , has[j] --; } }; for (int i = 0; i < 10; i ++) { del(i, i); if (t[i]) { for (int x = 1; x < 10; x ++) { if (i + x < 10 && has[i + x] && t[i]) { del(i, i + x); } } for (int x = 1; x < 10; x ++) { if (i - x >= 0 && has[i - x] && t[i]) { del(i, i - x); } } } } sort(ans.begin(), ans.end()); for (int i = 0; i < ans.size(); i ++) { auto x = ans[i]; cout << x[1] << '-' << x[2] << " \n"[i == ans.size() - 1]; } return 0; }
L2-3 简单的数数
思路
经典计数\(DP\)。
设 \(dp_{i,j}\) 表示第 \(i\) 位最后合并成 \(j\) 的方案数,则有转移方程:
代码
#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); int n; cin >> n; vector<int> a(n + 1); for (int i = 1; i <= n; i ++) { cin >> a[i]; } vector<Z> dp(10); dp[(a[1] + a[2]) % 10] += 1; dp[(a[1] * a[2]) % 10] += 1; for (int i = 3; i <= n; i ++) { vector<Z> ndp(10); for (int j = 0; j < 10; j ++) { ndp[(j + a[i]) % 10] += dp[j]; ndp[(j * a[i]) % 10] += dp[j]; } dp = ndp; } for (int i = 0; i < 10; i ++) { cout << dp[i] << "\n"; } return 0; }
L2-4 回家日
思路
最短路变式,其中维护最短改成取最解封时间大值即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, k; cin >> n >> m >> k; vector<int> c(n + 1); for (int i = 1; i <= n; i ++) { int x; cin >> x; c[x] = i; } vector g(n + 1, vector<int>()); for (int i = 0; i < m; i ++) { int x, y; cin >> x >> y; g[x].emplace_back(y); g[y].emplace_back(x); } vector<int> dis(n + 1); priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> Q; Q.emplace(c[k], k); while (Q.size()) { auto [d, u] = Q.top(); Q.pop(); if (dis[u]) continue; dis[u] = d; for (auto v : g[u]) { int nd = max(c[v], d); if (!dis[v] || nd < dis[v]) { Q.emplace(nd, v); } } } for (int i = 1; i <= n; i ++) { cout << dis[i] << " \n"[i == n]; } return 0; }
L3-1 忽远忽近的距离
思路
题目要求在小明的梦境中找到从起始幻境到目标幻境的最短路径,路径的权值由共享质因子决定。核心思路是将幻境和质因子抽象为图中的节点,通过堆优化Dijkstra算法求解最短路径。
对于每个幻境 \(a_i\),分解其所有质因子 \(z\),并创建虚拟节点 \(z + N\)(\(N\) 是幻境编号上限)。幻境 \(a_i\) 到其质因子虚拟节点 \(z + N\) 的边权为 \(\frac{a_i}{z}\),反向边权为 \(\frac{a_i}{z}\)。这样,若两个幻境 \(x\) 和 \(y\) 有共同质因子 \(z\),则可通过虚拟节点 \(z + N\) 连接,路径总权值为 \(\frac{x}{z} + \frac{y}{z} = \frac{x + y}{z}\)。
使用堆优化的 Dijkstra 算法。维护每个节点的最小距离 \(dis\) 和前驱节点 \(prev\)。每次从队列中取出当前距离最小的节点,松弛其邻接边。
从终点回溯前驱节点,得到完整路径。过滤掉质因子虚拟节点,仅保留实际幻境编号。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; constexpr int N = 1e6 + 10; int prime[N], id[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> a(n + 1); for (int i = 1; i <= n; i ++) { cin >> a[i]; id[a[i]] = 1; } using pdi = pair<int, int>; vector g(2 * N, vector<pdi>()); for (int i = 2; i < N; i ++) { if (!prime[i]) { for (int j = i; j < N; j += i) { if (id[j]) { g[j].emplace_back(j / i, i + N); g[i + N].emplace_back(j / i, j); } if (j > i) { prime[j] = 1; } } } } int st, ed; cin >> st >> ed; if (st == ed) { cout << 0 << "\n" << st << "\n"; return 0; } constexpr int INF = 1e9; vector<int> dis(2 * N, INF), prev(2 * N, -1); priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> Q; dis[st] = 0; Q.emplace(0, st); while (!Q.empty()) { auto [d, u] = Q.top(); Q.pop(); if (u == ed) break; if (d > dis[u]) continue; for (auto [w, v] : g[u]) { if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; prev[v] = u; Q.emplace(dis[v], v); } } } if (dis[ed] >= INF) { cout << "Wake up Xiaoming\n-1\n"; return 0; } vector<int> path; for (int u = ed; u != -1; u = prev[u]) { path.push_back(u); } reverse(path.begin(), path.end()); vector<int> rpath; for (int x : path) { if (x < N) { rpath.push_back(x); } } cout << dis[ed] << '\n'; for (int i = 0; i < rpath.size(); ++i) { cout << rpath[i] << " \n"[i == rpath.size() - 1] ; } return 0; }
思路
代码
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18692269
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步