Codeforces Round #804 (Div. 2) 题解
A. The Third Three Number Problem
题意
给你一个整数 ,构造满足等式 的三个整数 ,或说明这样的整数并不存在。
题目分析
根据样例猜了下如果是奇数则不存在,是偶数的话随便构造下就好。
AC代码
#include <bits/stdc++.h>
#include <limits>
#define IOS \
std::ios::sync_with_stdio(false); \
std::cin.tie(0); \
std::cout.tie(0);
using PII = std::pair<int, int>;
using ll = long long;
void solve()
{
ll n;
std::cin >> n;
if (n % 2 == 1)
std::cout << -1 << '\n';
else
std::cout << n / 2 << ' ' << 0 << ' ' << 0 << '\n';
}
int main()
{
IOS;
int t;
std::cin >> t;
while (t--)
solve();
return 0;
}
B. Almost Ternary Matrix
题意
给一个 行 列的矩阵黑白染色,使得其中每个单元格 的邻格中恰有两个不同色。
题目分析
跟着样例画了画发现按 和 交替染色即可。
AC代码
#include <bits/stdc++.h>
#include <limits>
#define IOS \
std::ios::sync_with_stdio(false); \
std::cin.tie(0); \
std::cout.tie(0);
using PII = std::pair<int, int>;
using ll = long long;
int map[55][55];
void solve()
{
int n, m;
std::cin >> n >> m;
for (int i = 1, f1 = 1; i <= n; i += 2, f1 ^= 1)
{
if (f1 & 1)
{
for (int j = 1, f2 = 1; j <= m; j += 2, f2 ^= 1)
{
if (f2 & 1)
map[i][j] = map[i + 1][j + 1] = 1;
else
map[i][j + 1] = map[i + 1][j] = 1;
}
}
else
{
for (int j = 1, f2 = 1; j <= m; j += 2, f2 ^= 1)
{
if (f2 & 1)
map[i][j + 1] = map[i + 1][j] = 1;
else
map[i][j] = map[i + 1][j + 1] = 1;
}
}
}
for (int i = 1; i <= n; ++i, std::cout << "\n")
for (int j = 1; j <= m; ++j, std::cout << " ")
std::cout << map[i][j];
}
int main()
{
IOS;
int t;
std::cin >> t;
while (t--)
solve();
return 0;
}
C - The Third Problem
题意
定义两个大小为 的排列 相似当且仅当:
- 对于所有区间 ,
现给定排列 ,求有多少个与之相似的排列 。
题目分析
首先玩样例,我们发现在 中,相对于 ,有些数的位置是恒定不变的;有些数虽然会变,但可变的位置数也不尽相同。考虑 的性质,可以发现以下性质:
- 如果 中 在包含 的最小区间中, 那么 中 也应在包含 的最小区间中
- 如果 中 在包含 的最小区间外, 那么 中 的位置理应与 中相同
因此如果 在当前最小区间 内,答案乘上 ,否则扩展当前最小区间。
AC代码
#include <bits/stdc++.h>
#define IOS \
std::ios::sync_with_stdio(false); \
std::cin.tie(0); \
std::cout.tie(0);
using PII = std::pair<int, int>;
using ll = long long;
const int P = 1e9 + 7;
ll solve()
{
int n;
ll ans = 1;
std::cin >> n;
std::vector<int> a(n + 1), pos(n + 1);
for (int i = 1; i <= n; ++i)
{
std::cin >> a[i];
pos[a[i]] = i;
}
int l = std::min(pos[0], pos[1]), r = std::max(pos[0], pos[1]);
for (int p = 2; p < n; ++p)
{
if (pos[p] < l || pos[p] > r)
l > pos[p] ? l = pos[p] : r = pos[p];
else
ans = ans * (r - l - p + 1) % P;
}
return ans;
}
int main()
{
IOS;
int t;
std::cin >> t;
while (t--)
std::cout << solve() << "\n";
return 0;
}
D. Almost Triple Deletions
题意
给你一个长度为 的数组 ,你可以执行下列操作任意次:
- 选择一个索引 ,如果对该索引有 ,则从数组中删除 和 ,并将数组的剩余部分串联起来
例如,如果 ,那么在进行 的操作后,所得数组将是 。
要求最后得到的数组中所有元素值相等,求其最大长度。
题目分析
赛时第一眼是DP,捣鼓半天发现不会d又转向贪心,结果贪不出来以为是构造,最后罚坐到结束也没什么好的思路。
首先看下数据范围 ,多半是个 的算法。我们可以发现当一个长度为 的数组满足下列条件时,它可以被完全删除:
-
是偶数
-
中任意元素的出现次数至多为
于是我们可以在 的时间内计算出 的每个子数组是否可以被完全删除。
设 表示以 结尾的最终数组的最大长度,初始化当 可被完全删除时 ,否则 。
转移有:
考虑最终数组中尾部连续的一段 也是可能被完全删除的,因此我们需要d到 ,并且 相当于万能通配符,那么答案即是 (要把 的长度减掉)。
看了下还有dalao用图论的方法做的,只能说我还是太菜了orz
AC代码
#include <bits/stdc++.h>
#define IOS \
std::ios::sync_with_stdio(false); \
std::cin.tie(0); \
std::cout.tie(0);
int solve()
{
int n;
std::cin >> n;
std::vector<int> a(n + 1), cnt(n + 1);
for (int i = 1; i <= n; ++i)
std::cin >> a[i];
std::vector<std::vector<int>> del(n + 1, std::vector<int>(n + 1));
std::vector<int> f(n + 2);
for (int i = 1; i <= n; ++i)
{
std::fill(cnt.begin(), cnt.end(), 0);
for (int j = i, mx = 0; j <= n; ++j)
{
mx = std::max(mx, ++cnt[a[j]]);
if ((j - i + 1) % 2 == 0 && mx <= (j - i + 1) / 2)
del[i][j] = 1;
}
}
for (int i = 1; i <= n + 1; ++i)
f[i] = del[1][i - 1];
f[1] = 1;
for (int i = 1; i <= n + 1; ++i)
for (int j = 1; j <= i - 1; ++j)
if (f[j] && (a[i] == a[j] || i == n + 1) && ((j + 1 > i - 1) || (del[j + 1][i - 1])))
f[i] = std::max(f[i], f[j] + 1);
return f[n + 1] - 1;
}
int main()
{
IOS;
int t;
std::cin >> t;
while (t--)
std::cout << solve() << "\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)