当前位置: 首页 > news >正文

Codeforces Round 1049 (Div. 2)


A. Shift Sort

题意:一个\(01\)串,每次可以选择\(i, j, k\)三个位置让它们左移或右移,求使得字符串升序的最小操作数。

记有\(cnt\)\(0\),如果一个\(0\)不在前\(cnt\)个位置里,那么它需要一次交换,且每次交换最多让一个\(0\)复位。所以这样位置的个数就是答案。

点击查看代码
#include <bits/stdc++.h>using i64 = long long;void solve() {int n;std::string s;std::cin >> n >> s;int cnt = std::ranges::count(s, '0');int ans = 0;for (int i = 0; i < cnt; ++ i) {ans += s[i] == '1';}std::cout << ans << "\n";
}int main() {std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);int t = 1;std::cin >> t;while (t -- ) {solve();}return 0;
}

B. Another Divisibility Problem

题意:给你一个\(x\),求一个\(y\),使得\(x+y\)整除\(x\)\(y\)拼接后的数字。

\(y\)\(k\)位,那么\(x+y = x\times 10^k + y\),减去一个\(x+y\)后等于\(x\times (10^k - 1)\),这个数要整除\(x+y\),那么\(x+y\)得是\(x\)的倍数,则\(y\)\(x\)的倍数。

点击查看代码
#include <bits/stdc++.h>using i64 = long long;void solve() {i64 x;std::cin >> x;for (i64 y = x; ; y += x) {std::string s = std::to_string(x) + std::to_string(y);i64 z = 0;for (auto & x : s) {z = z * 10 + x - '0';}if (z % (x + y) == 0) {std::cout << y << "\n";return;}}
}int main() {std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);int t = 1;std::cin >> t;while (t -- ) {solve();}return 0;
}

C. Ultimate Value

题意:一个数字\(a\)的代价为加上奇数位的和减去偶数的的和加\(cost\),其中\(cost\)为操作中产生的代价。\(Alice\)\(Bob\)两个人轮流操作,\(Alice\)先手,每次操作选择一个\(i, j(i < j)\)交换\(a_i, a_j\)\(cost\)增加\(j - i\),或者终止操作。\(Alice\)希望代价最大,\(Bob\)希望最小。求最终代价。

结论是\(Alice\)要么直接终止,要么操作一次后\(Bob\)直接终止。
因为如果轮到\(Bob\)操作,发现交换\(i, j\)会减少代价,那么之后\(Alice\)可以重复交换\(i, j\),这样数组没变,代价增加了\(2\times(j-i)\)。不如直接终止比赛。
那么问题就变为最多交换一次后的最大代价。
如果交换的数的位置奇偶性相同,代价为\(j-i\)
如果\(i\)是奇数,\(j\)是偶数,那么代价增加\(2\times a_j + j - 2\times a_i - i\)。这个可以从后往前做,记录一个\(max2\)表示偶数位置最大的\(2\times a_j - j\)
同理如果\(i\)是偶数,\(j\)是奇数,代价增加\(2\times a_i - i - 2\times a_j - j\)。也可以维护一个\(max1\)

点击查看代码
#include <bits/stdc++.h>using i64 = long long;void solve() {int n;std::cin >> n;std::vector<i64> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}i64 ans = 0;for (int i = 0; i < n; ++ i) {ans += i % 2 ? -a[i] : a[i];}i64 max = n % 2 ? n - 1 : n - 2;i64 max1 = -1e18, max2 = -1e18;for (int i = n - 1; i >= 0; -- i) {if (i % 2 == 0) {max = std::max(max, max2 - 2 * a[i] - (i + 1));max1 = std::max(max1, -2 * a[i] + (i + 1));} else {max = std::max(max, max1 + 2 * a[i] - (i + 1));max2 = std::max(max2, 2 * a[i] + (i + 1));}}std::cout << ans + max << "\n";
}int main() {std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);int t = 1;std::cin >> t;while (t -- ) {solve();}return 0;
}

D. A Cruel Segment's Thesis

题意:\(n\)\([l, r]\),价值原来的所有\(r-l\)的和,然后你需要两两匹配,价值加上\(l_i \leq x \leq r_i, l_j \leq y \leq r_j\)\(y - x\)的最大值。如果\(n\)是偶数则留一个不匹配。求最大价值。

一个区间对答案的贡献是要么被加上\(r\),要么被减去\(l\)。那么加上所有区间的\(r\)都是加上的,然后考虑选出\(\lfloor \frac{n}{2} \rfloor\)\(l_i\)减去,这样的区间因为之前加过\(r\),现在又减去\(l\),所以贡献加上\(-r_i - l_i\)。那么选出最大的\(\lfloor \frac{n}{2} \rfloor\)个这样的贡献。
然后如果\(n\)是偶数,可以匹配完,直接加上前一半就行,如果\(n\)是奇数,考虑枚举不匹配的区间,然后根据这个区间的\(-r_i - l_i\)是不是前\(\lfloor \frac{n}{2} \rfloor\)个大的讨论即可,选择使得贡献减少最小的区间。

点击查看代码
#include <bits/stdc++.h>using i64 = long long;void solve() {int n;std::cin >> n;i64 ans = 0;std::vector<i64> l(n), r(n);std::vector<std::pair<i64, int>> a(n);for (int i = 0; i < n; ++ i) {std::cin >> l[i] >> r[i];ans += r[i] - l[i];a[i] = {-r[i] - l[i], i};ans += r[i];}std::ranges::sort(a, std::greater<>());std::vector<int> st(n);i64 sum = 0;for (int i = 0; i < n / 2; ++ i) {sum += a[i].first;st[a[i].second] = 1;}if (n % 2 == 0) {ans += sum;} else {i64 max = -1e18;for (int i = 0; i < n; ++ i) {if (!st[i]) {max = std::max(max, -r[i] + sum);} else {max = std::max(max, sum - (-r[i] - l[i]) - r[i] + a[n / 2].first);}}ans += max;}std::cout << ans << "\n";
}int main() {std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);int t = 1;std::cin >> t;while (t -- ) {solve();}return 0;
}

E1. Prime Gaming (Easy Version)

题意:有\(n\)堆石头,每堆的石头数在\([1, m]\)之间。有些位置是可以操作的,\(Alice\)\(Bob\)轮流操作,每次选择一个可以操作的位置把这个位置上的石堆删掉,然后后面的往前移。最后剩下的一堆的石头数就是价值。\(Alice\)希望价值最大,\(Bob\)希望价值最小。求所有情况下的价值总和。
\(n \leq 20, m \leq 2\)

如果\(m=1\),答案是\(1\)
\(f[i][0/1][s]\)表示长度为\(i\)的数组,轮到\(Alice/Bob\)操作,且状态为\(s\)能否取到\(2\)。其中\(s\)是一个二进制数,第\(i\)位为\(0\)表示第\(i\)堆石头有一个石头,否则有两个石头。
那么枚举操作的位置,预处理一个\(ns[s][k]\)表示删掉\(s\)的第\(k\)位后的状态,就可以枚举操作的位置转移,其中\(Alice\)只需要有一个为\(1\)的状态能转移过来就是\(1\)\(Bob\)只需要有一个为\(0\)的状态转移过来就是\(0\)

点击查看代码
#include <bits/stdc++.h>using i64 = long long;const int mod = 1e9 + 7;bool f[21][2][1 << 20];
int ns[1 << 20][20];
int c[20];void init() {for (int s = 0; s < 1 << 20; ++ s) {int x = 0;for (int i = 0; i < 20; ++ i) {int y = x;for (int j = i + 1; j < 20; ++ j) {if (s >> j & 1) {y |= 1 << (j - 1);}}ns[s][i] = y;if (s >> i & 1) {x |= 1 << i;}}}
}void solve() {int n, m;std::cin >> n >> m;int k;std::cin >> k;memset(c, 0, sizeof c);for (int i = 0; i < k; ++ i) {int x;std::cin >> x;c[x - 1] = 1;}if (m == 1) {std::cout << 1 << "\n";return;}f[1][0][1] = f[1][1][1] = 1;f[1][0][0] = f[1][1][0] = 0;for (int i = 2; i <= n; ++ i) {for (int s = 0; s < 1 << i; ++ s) {f[i][0][s] = 0;for (int k = 0; k < i; ++ k) {if (c[k]) {f[i][0][s] |= f[i - 1][1][ns[s][k]];}}f[i][1][s] = 1;for (int k = 0; k < i; ++ k) {if (c[k]) {f[i][1][s] &= f[i - 1][0][ns[s][k]];}}}}int ans = 0;for (int s = 0; s < 1 << n; ++ s) {ans = (ans + f[n][0][s] + 1) % mod;}std::cout << ans << "\n";
}int main() {std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);int t = 1;init();std::cin >> t;while (t -- ) {solve();}return 0;
}
http://www.hskmm.com/?act=detail&tid=445

相关文章:

  • 课前问题思考1
  • huggingface
  • 安全不是一个功能-而是一个地基
  • Python基础-27 match-case 使用教程
  • 从0到1实现Transformer模型-CS336作业1
  • 准备工作之结构体[基于郝斌课程]
  • 软工课程第一次作业
  • java学习起航喽
  • 初始化树莓派(Raspberry Pi)系统并以 ssh 连接教程(只需读卡器、手机开热点,无需显示器) - tsunchi
  • 从windows 自动进入BIOS
  • 软件工程第一次作业
  • Morpheus 审计报告分享:AAVE 项目 Pool 合约地址更新导致的组合性风险
  • Offer发放革命:Moka软件如何将平均入职转化率提升25%
  • U3D动作游戏开发读书笔记--2.1一些通用的预备知识
  • 常见的一些Dos命令
  • AUC和ROC
  • CF
  • Word中VBA提取人名所在的页码
  • Ubuntu 安装 VSCode
  • A
  • ARC
  • 【2024-2025第二学期】助教工作学期总结
  • Ubuntu 安装 Git
  • systemctl命令
  • 对抗样本
  • 知识蒸馏
  • ssh相关问题
  • CSP 2025 游记
  • KVM虚拟机快照链创建,合并,删除及回滚研究
  • 第一次学dij qwq(p4779