2.27 CW 模拟赛 赛时记录

前言#

跟着策略做题, 注意数据检验, 不贪跟策略
一定要冷静, 放下, 耐心

看题#

T1#

给我打上麻将了, 真的假的

  • 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
    • 模拟操作情况, 找到最好开销, 注意最大和最小
    • 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
    • 构造: 先推性质, 不行打表
    • 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
    • 往往利用 dp , 结合约束处理当前方案
    • 先找到一组合法解, 然后在基础上进行调整
    • 一般优先考虑枚举性质更多, 或者确定性更强的元素

T2#

打表找规律, 可能有用

  • 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
    • 模拟操作情况, 找到最好开销, 注意最大和最小
    • 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
    • 构造: 先推性质, 不行打表
    • 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
    • 往往利用 dp , 结合约束处理当前方案
    • 先找到一组合法解, 然后在基础上进行调整
    • 一般优先考虑枚举性质更多, 或者确定性更强的元素
  • 定义约束, 要求满足约束的情况数
    • 逆向思维
    • 考虑不满足约束的情况, 数学表示约束

T3#

  • 交换相邻元素性质
    • ab , 交换 |ab|
    • 对于两个串的定位问题, 每个元素定位的花费就是关于其的逆序对个数
      证明: 从大权值到小权值, 逐个固定位置
    • 往往用固定之前的部分, 移动当前的部分来解决
  • 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
    • 模拟操作情况, 找到最好开销, 注意最大和最小
    • 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
    • 构造: 先推性质, 不行打表
    • 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
    • 往往利用 dp , 结合约束处理当前方案
    • 先找到一组合法解, 然后在基础上进行调整
    • 一般优先考虑枚举性质更多, 或者确定性更强的元素

T4#

不好, 最后一题放期望
那只能看看了


跟着策略走, 不贪, 数据检验

T1#

思路#

题意

给定 nn 个在 [1,m][1, m] 范围内的序列 aa
要求把序列 aa 划分成形如 {x,x,x} or {x,x+1,x+2}\{x, x, x\} \textrm{ or } \{x, x + 1, x + 2\} 这样的段的方案数

题目显然提示先搞出桶, 所以记 pi 表示数字 i 出现的次数
fi 表示用完前 i1 个数字, 没有使用过 i 的方案数

转移只有两种

  • (1) 对于 i,i+1,i+2 , 各自使用
  • (2) 对于 i,i+1,i+2 , 一个数字单独使用 3

每次转移, 如果只是单独使用 i , 那么转移到 fi+1
否则转移到 i+3
现在的问题是, 对于 (1),(2) 两种转移, 如何完全枚举所有情况

不妨枚举使用 (1) 转移的次数, 记为 j
那么如果 pipij,pi+1pi+1j,pi+2pi+2j 之后, pi,pi+1,pi+2 都是 3 的倍数, 那么可以转移
总复杂度是 O(nm) 左右

不想数据检验, 先打一个试一下
挂的有点多, 先手搞一下
容易发现没考虑好

感觉可以用区间 dp 的思路去搞

f[L,R] 表示清空值域区间 [L,R] 的方案数
初始化先预处理长度为 1,3 的区间

然后不难列出式子

f[L,R]{f[L,R1], case pR1 mod 3=0f[L+1,R], case pL+1 mod 3=0f[L+3,R],f[L,R3],

只需要注意判断区间的合法性, 预处理长度为 3 的区间构造方法数即可

有点担心这个的正确性, 先看下后面有没有更好拿的分
发现还是假的, 不妨修改定义

f 表示用 (1) 操作把剩下的都变成 3 倍数的方案数

实现#

框架#

预处理

  • f 数组
  • 任意连续三个区间中, 有多少种情况把他们清零 (必须使用至少一次 (1) 操作)

转移

T2#

思路#

题意

构造字典序最小的排列, 使得对于 1in1 \leq i \leq n , 都有 piik|p_i - i| \geq k

对于位置 i , pi[i+k,n][1,ik]
不太会, 不浪费时间了, nn! 打了跑, 记得观察一下规律万一瞪出来了呢

真瞪出来了

代码
#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;
}

T3#

你想知道的还挺多

思路#

题意

给定 pi,wip_i, w_i
一次交换定义为对 pi,pi+1p_{i} , p_{i + 1} 的操作
要求 wpi+wpi+1Ww_{p_i} + w_{p_{i + 1}} \leq W , 满足要求可以 swap{pi,pi+1}\textrm{swap}\{p_i, p_{i + 1}\}

但是这题拿个 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;
}

曹了呀, 大样例飞不过去, 怎么办怎么办怎么办
不管了, 急急急急急急, 直接去 T4
cnm , vscode 配置问题

T4#

思路#

直接模拟

对于一种状态 S , 考虑计算需要多少钱
贪心的在他检票的时候, 如果当前没有票, 就买一张

不管了, 这题暴力先给我丢了, 先去冲 T1

posted @   Yorg  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示