2026年5月20日 · 比赛 · 1 分钟阅读

CSP-S 2023 赛后复盘:那些「看起来会了」的时刻

考完感觉良好,但出分后被锤。记录一下我是怎么一步步把本该拿的分数丢掉的。

AI 摘要

考前我模拟了 6 套真题,每套都稳定在 400+。正式考完走出考场的时候,我觉得这次稳了。

考前我模拟了 6 套真题,每套都稳定在 400+。正式考完走出考场的时候,我觉得这次稳了。

出分:312 分。

丢分复盘

T2:把「至少」看成了「恰好」

题目问「至少需要多少次操作」,我写的判定是「恰好等于」。

// 错误:只检查了恰好等于最优值的情况
if (calc(a) == OPT) flag = true;

正确应该是 >= OPT。但更致命的是,我用 calc(a) == OPT 作为「这个分支合法」的前提,导致后面所有剪枝全在这个错误前提下剪枝。

1 分变 0 分,而且是连锁反应。

T4:贪心缺了证明

第三问我用的贪心,样例过了,小数据也过了,但大数据 WA。

我的贪心是「每次取剩余最大的那一堆」。手推几个例子没问题,但我没找到反例——没找到不等于没有。考场上我用「模拟了很多小数据都过」来说服自己,这是典型的自我说服。

后来复盘构造出了反例:只需要把「最大的那一堆」改成「第二大的那一堆里最靠前的那堆」,就 WA 了。

复盘方法

这次之后我改了一个习惯:每道题写完正解,必须花 5 分钟构造反例。

具体做法:

  1. 写一个小数据暴力;
  2. 对正解跑暴力对拍,跑 10 万组随机;
  3. 记录卡住的一组,人工分析。

这个「暴力对拍」的习惯我从这次才开始建立。之前我都是「样例过了 + 手推几个例子」就交卷了。

// 对拍模板(我现在所有比赛的标配)
#include <bits/stdc++.h>
using namespace std;

int main() {
    mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
    for (int T = 1; T <= 100000; T++) {
        // 生成随机数据 → 写文件
        // 跑暴力和正解 → 比对
    }
}

当然考场上手写对拍不现实。但平时练的时候必须写,因为考场上你的「感觉对」是不值钱的。

一点想法

CSP 这种比赛,题目的区分度往往不在算法难度,而在你有没有把题目读准。

T2 那个「至少 vs 恰好」,如果我多读一遍题,可能就不会错。而多读一遍题的成本是 30 秒,收益是 20 分。

我那年少花了那 30 秒。


明年再战。

© Yuki · 本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
看板娘
ESC

输入关键词开始搜索

提示:↑ ↓ 选择 · Enter 打开 · Esc 关闭