Welcome To Ke_scholar's Blog|

Ke_scholar

园龄:2年1个月粉丝:30关注:10

2025-01-26 23:15阅读: 9评论: 0推荐: 0

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\) 的方案数,则有转移方程:

\[dp_{i,j + a_i \pmod{10}} += dp_{i-1,j} \]

\[dp_{i,j \times a_i \pmod{10}} += dp_{i-1,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 中国大陆许可协议进行许可。

posted @   Ke_scholar  阅读(9)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起