先说结论
阅读程序题不是考你会不会写代码,而是考你能不能像 CPU 一样,一行一行把程序执行出来。
而人脑的工作记忆只有三四个格子——变量一多、递归一深,靠「心算」必错。
草稿纸才是你的第二块内存。
这 40 分到底考什么
| 题型 | 题量 | 分值 | 建议用时 | 难度 |
|---|---|---|---|---|
| 单项选择题 | 15 题 | 30 分 | 20—25 分钟 | ★ |
| 阅读程序题 | 3 大题 | 40 分 | 40—50 分钟 | ★★★ |
| 完善程序题 | 2 大题 | 30 分 | 30—40 分钟 | ★★ |
阅读程序题里常见的问法就这几类:
- 给输入求输出:代码给定输入,问最后输出什么;
- 问程序功能:这段代码实现了什么算法;
- 判断说法正误:判断题正确选 A、错误选 B,别搞反;
- 问边界条件:
n取 0、取 1 时会怎样; - 问时间复杂度:这段代码跑一遍要多久。
手动模拟三步法
别一上来就盯着代码一行一行硬算,按这三步走:

第 1 步:30 秒定框架
先快速扫一遍代码,看函数名、注释、循环结构、有没有递归、主函数在干什么:
- 看到
f(n) = n * f(n-1)→ 阶乘 - 看到双层循环 + 相邻比较交换 → 冒泡排序
- 看到
f(n) = f(n-1) + f(n-2)→ 斐波那契
方向对了,读起来就不慌。
第 2 步:模拟执行,画变量表(核心,2—5 分钟)
一行一行走,每执行完一行就把变量的新值记进表里,别等循环跑完再回头算。
标准格式:
行号 | 变量1 | 变量2 | … | 输出
- 循环体每迭代一次,就新开一行;
- 遇到函数调用,单独画一个调用栈。
第 3 步:看问题,回表找答案(30 秒)
判断题直接查你的变量表;选择题用排除法 + 代入法。
实战一:递归题 —— 画调用栈
int f(int n) {
if (n <= 1) return n; // ① 终止条件
return f(n - 1) + f(n - 3); // ② 递归调用
}
int main() {
cout << f(6);
return 0;
}
Step 1|定框架:f 里两组递归调用,典型「递归求值」题,不用管实际意义,只要算出 f(6)。
Step 2|画调用栈,从最底层往上回代。递归不能从 f(6) 往下硬算,要先把最底层能直接算的算出来,再一层层往上代:
f(6)
├─ f(5)
│ ├─ f(4)
│ │ ├─ f(3)
│ │ │ ├─ f(2)
│ │ │ │ ├─ f(1) → 1
│ │ │ │ └─ f(-1) → -1 ← n ≤ 1 直接返回 n
│ │ │ │ 所以 f(2) = 1 + (-1) = 0
│ │ │ └─ f(0) → 0
│ │ │ 所以 f(3) = 0 + 0 = 0
│ │ └─ f(1) → 1
│ │ 所以 f(4) = 0 + 1 = 1
│ └─ f(2) → 0
│ 所以 f(5) = 1 + 0 = 1
└─ f(3) → 0
所以 f(6) = 1 + 0 = 1
Step 3|得答案:输出 1。
⚠️ 这里的坑非常典型:终止条件是
return n,不是return 1。 所以当n < 1时返回的是那个负数本身(f(-1) = -1),很多人想当然以为「小于 1 就返回 0」,一步错、步步错。
实战二:循环题 —— 画变量表
int s = 0;
for (int i = 1; i <= 5; i++) {
if (i % 2 == 1) s += i;
else s -= i;
}
cout << s;
逐行记录,答案一眼可见:
| 迭代 | i | i % 2 | 操作 | s |
|---|---|---|---|---|
| 初始 | — | — | — | 0 |
| 1 | 1 | 1 | s += 1 |
1 |
| 2 | 2 | 0 | s -= 2 |
-1 |
| 3 | 3 | 1 | s += 3 |
2 |
| 4 | 4 | 0 | s -= 4 |
-2 |
| 5 | 5 | 1 | s += 5 |
3 |
即 \(s = 1-2+3-4+5 = 3\)。

3 个「必动笔」场景
- 循环 → 画变量表。 只要循环里牵扯 2 个以上变量(
s累加、i变化),就一行一行记下来。 - 递归 → 画调用栈。 从最底层往上回代,绝不跳步——递归题九成错在「跳步」上。
- 数组 / 指针 → 画下标变化。 特别注意:
swap用引用传参时,形参改了实参就变;但如果两个值本来就相等,「交换」了也看不出变化——别以为代码没执行。
3 条铁律
- 先看框架,再逐行读。 别一上来就抠细节,先花 30 秒弄清它在干嘛。
- 画变量表!画变量表! 3 个以上变量脑子就记不住了,别硬撑。
- 递归必画调用栈,从底部往上算。 循环画表,递归画树,两码事。
考点速记
- 阅读程序题 3 大题 40 分,建议 40—50 分钟,是初赛分值最高、最拉差距的板块。
- 判断题正确选 A、错误选 B,每年都有人搞反。
- 递归先看终止条件返回的是什么(
return n还是return 1),再看递归式。 - 遇到
n = 0 / 1 / -1这类边界,一定要单独代入验证。 - 草稿纸 + 变量表 > 大脑心算,这是唯一「稳」的办法。
思考题
int g(int n) {
if (n <= 1) return 1;
return g(n - 1) + g(n - 2);
}
g(5) 输出多少?如果终止条件改成 return n,结果又是多少?
答案
`return 1` 时:**8**。 ``` g(0)=1 g(1)=1 g(2)=g(1)+g(0)=2 g(3)=g(2)+g(1)=3 g(4)=g(3)+g(2)=5 g(5)=g(4)+g(3)=8 ``` 改成 `return n` 时:**5**。 ``` g(0)=0 g(1)=1 g(2)=1+0=1 g(3)=1+1=2 g(4)=2+1=3 g(5)=3+2=5 ``` **一个字的终止条件差别,结果从 8 变成 5**——这就是为什么要一字一句读终止条件。参考整理自公众号「开心算法」《CSP 初赛阅读程序题,靠「手动模拟」拿满 40 分》。



