2.27 CW 模拟赛 赛时记录
前言
跟着策略做题, 注意数据检验, 不贪跟策略
一定要冷静, 放下, 耐心
看题
\(\rm{T1}\)
给我打上麻将了, 真的假的
- 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
- 模拟操作情况, 找到最好开销, 注意最大和最小
- 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
- 构造: 先推性质, 不行打表
- 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
- 往往利用 \(\rm{dp}\) , 结合约束处理当前方案
- 先找到一组合法解, 然后在基础上进行调整
- 一般优先考虑枚举性质更多, 或者确定性更强的元素
\(\rm{T2}\)
打表找规律, 可能有用
- 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
- 模拟操作情况, 找到最好开销, 注意最大和最小
- 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
- 构造: 先推性质, 不行打表
- 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
- 往往利用 \(\rm{dp}\) , 结合约束处理当前方案
- 先找到一组合法解, 然后在基础上进行调整
- 一般优先考虑枚举性质更多, 或者确定性更强的元素
- 定义约束, 要求满足约束的情况数
- 逆向思维
- 考虑不满足约束的情况, 数学表示约束
\(\rm{T3}\)
- 交换相邻元素性质
- 从 \(a\) 到 \(b\) , 交换 \(|a - b|\) 次
- 对于两个串的定位问题, 每个元素定位的花费就是关于其的逆序对个数
证明: 从大权值到小权值, 逐个固定位置 - 往往用固定之前的部分, 移动当前的部分来解决
- 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
- 模拟操作情况, 找到最好开销, 注意最大和最小
- 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
- 构造: 先推性质, 不行打表
- 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
- 往往利用 \(\rm{dp}\) , 结合约束处理当前方案
- 先找到一组合法解, 然后在基础上进行调整
- 一般优先考虑枚举性质更多, 或者确定性更强的元素
\(\rm{T4}\)
不好, 最后一题放期望
那只能看看了
跟着策略走, 不贪, 数据检验
\(\rm{T1}\)
思路
题意
给定 个在 范围内的序列
要求把序列 划分成形如 这样的段的方案数
题目显然提示先搞出桶, 所以记 \(p_i\) 表示数字 \(i\) 出现的次数
记 \(f_i\) 表示用完前 \(i - 1\) 个数字, 没有使用过 \(i\) 的方案数
转移只有两种
- \((1)\) 对于 \(i, i + 1, i + 2\) , 各自使用
- \((2)\) 对于 \(i, i + 1, i + 2\) , 一个数字单独使用 \(3\) 个
每次转移, 如果只是单独使用 \(i\) , 那么转移到 \(f_{i + 1}\)
否则转移到 \(i + 3\)
现在的问题是, 对于 \((1), (2)\) 两种转移, 如何完全枚举所有情况
不妨枚举使用 \((1)\) 转移的次数, 记为 \(j\)
那么如果 \(p_i \gets p_i - j, p_{i + 1} \gets p_{i + 1} - j, p_{i + 2} \gets p_{i + 2} - j\) 之后, \(p_i, p_{i + 1}, p_{i + 2}\) 都是 \(3\) 的倍数, 那么可以转移
总复杂度是 \(\mathcal{O} (nm)\) 左右
不想数据检验, 先打一个试一下
挂的有点多, 先手搞一下
容易发现没考虑好
感觉可以用区间 \(\rm{dp}\) 的思路去搞
令 \(f_{[L, R]}\) 表示清空值域区间 \([L, R]\) 的方案数
初始化先预处理长度为 \(1, 3\) 的区间
然后不难列出式子
只需要注意判断区间的合法性, 预处理长度为 \(3\) 的区间构造方法数即可
有点担心这个的正确性, 先看下后面有没有更好拿的分
发现还是假的, 不妨修改定义
\(f\) 表示用 \((1)\) 操作把剩下的都变成 \(3\) 倍数的方案数
实现
框架
预处理
- \(f\) 数组
- 任意连续三个区间中, 有多少种情况把他们清零 \((\)必须使用至少一次 \((1)\) 操作\()\)
转移
\(\rm{T2}\)
思路
题意
构造字典序最小的排列, 使得对于 , 都有
对于位置 \(i\) , \(p_i \in [i + k, n] \cup [1, i - k]\)
不太会, 不浪费时间了, \(n n!\) 打了跑, 记得观察一下规律万一瞪出来了呢
真瞪出来了
代码
#include <bits/stdc++.h>
const int MAXN = 20;
int n, k;
int bas[MAXN], ans[MAXN];
int res[300020];
int main() {
scanf("%d %d", &n, &k);
if (n <= 10) {
memset(ans, 0x3f, sizeof ans);
for (int i = 1; i <= n; i++) bas[i] = i;
do {
bool flag = true;
for (int i = 1; i <= n; i++) {
if (std::abs(bas[i] - i) < k) { flag = false; break; }
}
if (flag) {
bool better = false;
for (int i = 1; i <= n; i++) {
if (ans[i] != bas[i]) {
if (ans[i] > bas[i]) better = true;
break;
}
}
if (better) {
for (int i = 1; i <= n; i++) ans[i] = bas[i];
}
}
} while (std::next_permutation(bas + 1, bas + n + 1));
if (ans[1] > n) printf("-1");
else for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
} else {
int len = 2 * k;
for (int i = 1; i <= n; i += len) {
for (int j = i + k; j <= i + len - 1; j++) res[j - k] = j;
for (int j = i; j <= i + k - 1; j++) res[j + k] = j;
}
for (int i = 1; i <= n; i++) printf("%d ", res[i]);
}
return 0;
}
\(\rm{T3}\)
你想知道的还挺多
思路
题意
给定
一次交换定义为对 的操作
要求 , 满足要求可以
但是这题拿个 \(30\) 真的差不多了, 遂决定直接干个大聪明暴力
代码
#include <bits/stdc++.h>
const int MAXN = 11;
int n, W;
int w[MAXN];
std::vector<int> p;
std::map<std::vector<int>, bool> exists;
std::map<int, std::vector<int>> num; int cnt = 0;
void dfs(int now) {
for (int i = 2; i <= n; i++) {
if (w[num[now][i]] + w[num[now][i - 1]] <= W) {
std::vector<int> nxt = num[now];
std::swap(nxt[i], nxt[i - 1]);
if (exists[nxt]) continue;
else {
exists[nxt] = true, num[++cnt] = nxt;
dfs(cnt);
}
}
}
}
int main() {
scanf("%d %d", &n, &W);
p.resize(11);
for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
exists[p] = true; num[++cnt] = p;
dfs(cnt);
std::vector<int> res; res.resize(11);
for (int i = 1; i <= n; i++) res[i] = 0x3f3f3f3f;
int ans = 0;
for (int i = 1; i <= cnt; i++) {
bool better = false;
for (int j = 1; j <= n; j++) {
if (res[j] != num[i][j]) {
if (res[j] > num[i][j]) better = true;
break;
}
}
if (better) {
for (int j = 1; j <= n; j++) res[j] = num[i][j];
}
}
printf("%d\n", cnt);
for (int j = 1; j <= n; j++) printf("%d ", res[j]);
return 0;
}
曹了呀, 大样例飞不过去, 怎么办怎么办怎么办
不管了, 急急急急急急, 直接去 \(\rm{T4}\)
\(\textrm{cnm}\) , \(\textrm{vscode}\) 配置问题
\(\rm{T4}\)
思路
直接模拟
对于一种状态 \(\mathbb{S}\) , 考虑计算需要多少钱
贪心的在他检票的时候, 如果当前没有票, 就买一张
不管了, 这题暴力先给我丢了, 先去冲 \(\rm{T1}\)

浙公网安备 33010602011771号