Educational Codeforces Round 174 (Rated for Div. 2)
A. Was there an Array?
题目大意
在一个数组中,如果一个数和它相邻的两个数字都相等,那么在特征数组中它就是1,否则为0(最两侧的数字不计,特征数组长度为n-2),现在给定特征数组,问能否构造出数组满足这个特征数组
解题思路
构造不出来就是有冲突,相邻不相等可以随意构造,而相等则存在限制,显然这里可能有的冲突就是x两侧的值已经固定且和x相等,但是特征数组却显示不相等,因此只需要判断是否存在特征数组101子串即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n;
std::cin >> n;
std::string s;
for (int i = 0; i < n - 2; i++) {
int x;
std::cin >> x;
s += '0' + x;
}
if (s.find("101") == -1) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
}
}
B. Set of Strangers
题目大意
给你一个数字矩阵,每次可以修改所有数值为x且上下左右四个方向不相邻的数字为y,问至少修改多少次能让矩阵的数字全都一样
解题思路
让这些数字变成没出现过的新数字肯定不优,因此标记出现的数字,最后在这里找即可,可以发现同一个数字修改的次数要么是1要么是2,因此两层循环暴力搜索最后去掉一次最大操作(变成那个数字)即可即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, m;
std::cin >> n >> m;
std::vector<int> cnt(n * m + 1), f(n * m + 1);
std::vector<std::vector<int>> g(n, std::vector<int>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
std::cin >> g[i][j];
f[g[i][j]] = 1;
cnt[g[i][j]] = 1;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (j + 1 < m && g[i][j + 1] == g[i][j] || i + 1 < n && g[i + 1][j] == g[i][j]) {
cnt[g[i][j]] = 2;
}
}
}
int ans = 0, maxn = 0;
for (int i = 1; i <= n * m; i++) {
if (f[i]) {
ans += cnt[i];
maxn = std::max(maxn, cnt[i]);
}
}
std::cout << ans - maxn << "\n";
}
}
C. Beautiful Sequence
题目大意
一个数组中除了最两侧的数字,每一个数字都满足左边有一个数字比它小,右边有一个数字比它大,那么这个就是漂亮数组。现在给定一个元素只含1-3的数组,问有多少子序列是漂亮数组,对答案模998244353
解题思路
显然满足的子序列只有最左边是1最右边是3,中间全是2的。预处理出模意义下2的幂和逆元以及区间内2的数量,再对遇到1和3的时候分类处理即可,例如i处是1,j处是3,则这一部分的贡献就是
代码实现
#include <bits/stdc++.h>>
using i64 = long long;
const int MOD = 998244353;
const int N = 2e5 + 10;
i64 ksm(i64 a, i64 b) {
i64 res = 1;
a %= MOD;
while (b) {
if (b & 1) {
res = res * a % MOD;
}
a = a * a % MOD;
b >>= 1;
}
return res;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::vector<i64> pow2(N, 1), inv2(N, 1);
for (int i = 1; i < N; i++) {
pow2[i] = (pow2[i - 1] * 2) % MOD;
inv2[i] = (inv2[i - 1] * ksm(2, MOD - 2)) % MOD;
}
int tt;
std::cin >> tt;
while (tt--) {
int n;
std::cin >> n;
std::vector<int> a(n + 1), pre(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
pre[i] = pre[i - 1] + (a[i] == 2);
}
i64 ans = 0, sum = 0, cnt = 0;
for (int i = 1; i <= n; i++) {
if (a[i] == 1) {
sum = (sum + inv2[pre[i]]) % MOD;
cnt++;
} else if (a[i] == 3){
ans = (ans + ((pow2[pre[i - 1]] * sum) % MOD - cnt) % MOD + MOD) % MOD;
}
}
std::cout << ans % MOD << "\n";
}
}
D. Palindrome Shuffle
题目大意
给你一个偶数长度的字符串,你可以对它的子串进行一次重排然后把他变成回文串,问最短子串是多少
解题思路
先对两侧的回文部分进行处理,取出中间非回文的部分,再统计字母数量,由于最后是偶数长度的回文串,所以一定可以分成两半,先对字母数量减半得到构成半个回文串的字母数量,再从一侧扫描过去不断减去当前的字符,直到这一侧的数量不满足半个回文串要求的数量,除此之外还有一种特殊情况,也就是恰好平分了数量,这时还要从中间往两侧扩展一次更新一下答案,最后对左右两侧扫一遍的答案取小即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
std::string s;
std::cin >> s;
int l = 0, r = s.size();
while (r - l >= 2 && s[r - 1] == s[l]) {
l++, r--;
}
s = s.substr(l, r - l);
std::vector<int> cnt(26);
for (auto ch : s) {
cnt[ch - 'a']++;
}
for (auto& x : cnt) {
x /= 2;
}
int ans = s.size();
for (int i = 0, len = s.size(); i < 2; i++, len = s.size(), std::reverse(s.begin(), s.end())) {
auto c = cnt;
for (auto ch : s) {
if (c[ch - 'a'] == 0) {
break;
}
len--;
c[ch - 'a']--;
}
if (2 * len == s.size()) {
while (len) {
if (s[len - 1] != s[s.size() - len]) {
break;
}
len--;
}
}
ans = std::min(ans, len);
}
std::cout << ans << "\n";
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具