这是什么: 一张常备速查表。不用从头看——卡住的时候按症状翻到对应那一节。
为什么给你: 自学最大的杀手不是"不会做",是"卡住了不知道下一步该干什么",然后就停在那里了。这份卡片的目标是:任何时候你都有下一步可做。
| 你看到的 | 翻到 |
|---|---|
| 一堆红字,程序根本没跑起来 | 一、编译错误 |
| 编译过了,但黑窗口闪一下就没了 / 弹出崩溃提示 | 三、运行时崩溃 |
| 跑出来了,但答案不对 | 二、答案错了 |
| 样例对了,交上去只得了一部分分 | 四、超时 + 二(边界数据) |
| 本地对、评测机错 | 五、本地对评测机错 |
| 什么都对,但是 0 分 | 六、爆零清单 |
📝 永远从第一条报错看起。 编译器出错后会连锁反应,后面几十行都是被第一条带歪的,改掉第一条往往全清。
| 报错关键词 | 中文意思 | 十有八九是 |
|---|---|---|
expected ';' before 'xxx' |
在 xxx 之前少个分号 | 分号要加在 xxx 前面那一行的末尾。⚠️
不同版本编译器报的行号可能是漏分号那行,也可能是下一行——认准报错里的
before 'xxx',往 xxx 前面找 |
'xxx' was not declared in this scope |
xxx 没定义 | 变量名拼错、大小写不对、或函数定义写在了 main
后面 |
expected '}' at end of input |
大括号没配对 | 少了一个 }。按 Ctrl+A
全选后重新缩进一遍,一眼就能看出来 |
invalid operands of types 'xxx' and 'yyy' |
两种类型不能这么运算 | 拿 string 去做减法、拿 char
当数组下标之类 |
no matching function for call to 'xxx' |
找不到匹配的函数 | 参数个数或类型不对,比如 sort(a, n) 少写了
a + n |
⚠️ was not declared in this scope
最常见的隐藏原因是函数顺序。 C++ 从上往下读,main
里调用的函数必须写在 main 前面(L06 讲过)。
<<
打架cout << a & b << endl;
报错会莫名其妙地指向类型问题。原因是 <<
的优先级高于 &,编译器读成了
(cout << a) & (b << endl)。
cout << (a & b) << endl; // 套括号按这个顺序做,不要跳步。
把输入缩到你能用纸笔算出答案的规模——n = 1、n = 2、全相同、全不同。然后:
📝 90% 的逻辑错误在 n = 1 或 n = 2 时就会暴露。 大数据只会让你看不清。
在循环里插
cout,把你以为的值打出来看:
for (int i = 1; i <= n; i++) {
cout << "[debug] i=" << i << " sum=" << sum << endl; // 临时
...
}⚠️ 调试输出必须加个显眼的前缀(比如
[debug]),交卷前全部删掉。 忘删 = 答案错 = 0
分,这条在爆零清单里。
| 查什么 | 典型错法 |
|---|---|
| 循环边界 | i < n 写成
i <= n(数组越界);i = 0 写成
i = 1(漏第一个) |
| 初始值 | 求和的 sum 没清零;打擂台找最大值初始化成
0,但数据里有负数 |
| 数据类型 | 该 long long 的写了 int(L01
乘方题的坑) |
| 整数除法 | a / b 悄悄砍掉了小数;平均数要写
sum * 1.0 / n |
| 特殊输入 | n = 0、全部相同、答案是负数、题目允许的最小/最大值 |
写两个程序:一个是一定对但很慢的暴力,一个是你的正式解法。再写个小程序随机生成数据,让两个程序跑同一份输入,比对输出。
1. baoli.cpp —— 三重循环也无所谓,只要保证对
2. mine.cpp —— 你的正式解法
3. gen.cpp —— 随机造小数据(n 取 5~10 就够)
4. 反复跑,一旦两个输出不一样,立刻就抓到了一组反例
📝 对拍抓到的反例通常很小,可以直接手玩——这就绕回第 1 步了,而且这次你知道该玩哪组数据。
黑窗口闪退、弹出"停止工作"、洛谷返回 RE,基本就这三个原因:
| 原因 | 怎么查 |
|---|---|
| 数组越界 | 数组开够了吗?题目说 n ≤ 10⁵,你开的是 a[100005] 还是
a[1005]?下标从 1 开始的话有没有多留一格? |
| 除以 0 / 模 0 | 分母是变量时,它有没有可能是 0? |
| 递归没边界 | L06 讲过:漏了终止条件,C++ 不像 Python 会报
RecursionError,它闷声崩溃 |
⚠️ 大数组必须开在 main 外面。
int a[1000005]; 写在 main
里会撑爆栈空间,直接崩。写在函数外(全局)就没这个问题,而且全局数组自动清零。
回到 L01 的复杂度预算表:评测机 1 秒约 10⁸ 次简单运算。
| n 的范围 | 能接受的复杂度 |
|---|---|
| n ≤ 20 | O(2ⁿ) |
| n ≤ 500 | O(n³) |
| n ≤ 5000 | O(n²) |
| n ≤ 10⁶ | O(n) ~ O(n log n) |
| n ≤ 10⁹ | O(√n)、O(log n) 或 O(1) |
📝 先看数据范围倒推你"最多能用几层循环",再决定写法。 写完才发现超时,往往要整个推倒重来。
在最内层加个计数器:
long long steps = 0;
for (...) {
for (...) {
steps++;
...
}
}
cout << "[debug] steps=" << steps << endl;跑一遍最大规模的数据,看 steps
是不是远超 10⁸。这比盯着代码猜快得多。
| 情况 | 说明 |
|---|---|
循环里反复 sort |
每次 O(n log n),n 次就是 O(n² log n)。改用 S3 的计数数组"边加边查" |
循环条件里调 sqrt / size() |
每轮都重算一次。判质数写 i * i <= n,别写
i <= sqrt(n) |
cin / cout 读入 10⁶ 级数据 |
加一行 ios::sync_with_stdio(false); 在
main 开头(⚠️ 加了之后不能再混用
scanf/printf) |
| 特殊数据让循环退化 | L01 乘方题:a = 1 时循环真的会跑 10⁹ 次。想想有没有哪种输入会让你的循环"停不下来" |
这类最难查,因为你在本地复现不出来。按可能性排序:
int 溢出。 本地样例数字小,大数据爆
int。改 long long 试试。sort 的相等元素顺序。 见
S2——本地的顺序和评测机可能不同。front()、空栈调
top()、cmp 里写了
<=。这类"本地看起来正常"纯属运气。复赛最后 30 分钟停止开新题,逐条过这个清单。这些都是"程序完全正确但拿 0 分"的死法。
📝 完整的 freopen 用法和 Dev-C++ 里的测试步骤见
freopen函数用法教程.md,考前再过一遍。
自学最怕死磕。设一个闹钟,卡住 15 分钟就换动作:
S8_真题分级提示.md 里对应题目的提示
1(只告诉你往哪个方向想)⚠️ 不要直接去搜别人的完整代码。 抄一遍能过,但下次遇到同类题你还是不会——你缺的从来不是代码,是"怎么想到"的那一步。三层提示就是拆开给你看那一步的。
📝 把每次卡住的地方记在一个本子上。 到第 7 次课复盘时,这个本子比任何讲义都值钱——它精确地告诉你,你的短板到底在哪。