408 大题书写实践
本页是 408 大题书写规范 的实践手册。讲义回答“为什么这样写”,本页解决“拿到一道具体题后怎样落笔”。
大题书写的目标不是接近参考答案的字数,而是用尽可能明确的文字暴露采分点:
阅卷人能找到结论,也能沿着必要依据复核结论。
先判断题目要你交付什么
读完一个小问,先圈出动词。动词决定最低书写量。
| 题目动词 | 应交付的内容 | 常见缺陷 |
|---|---|---|
| 写出、指出、填写 | 对象明确的结论 | 写了原理,却没有明确答案 |
| 是否、能否 | 是/否 + 题目要求的理由 | 只写“能”“不能” |
| 说明理由、为什么 | 结论 + 决定性判据 + 题目条件 | 默写整段定义,没有结合本题 |
| 计算、求 | 公式或规则 + 代入 + 结果和单位 | 只写最终数字 |
| 推导、证明 | 已知关系 + 关键变形 + 结论 | 直接背结论 |
| 列举、哪些 | 按对象分点列全 | 多写不确定项,污染正确答案 |
| 设计、描述算法 | 基本思想 + 实现 + 必要分析 | 只有代码,或只有自然语言 |
然后看分值估计采分点数量。1 分题有时只需要一个准确结论;2 分题常见“结论 + 理由”或两个并列点;更高分的小问通常需要多个步骤。但分值不是字数换算表,最终仍要看题目动词和信息结构。
一个可伸缩的答案骨架
不要机械地给每道题都套三段话。下面这个骨架可以按题目要求缩放:
1. 结论:直接回答所问对象。
2. 依据:写决定结论的定义、公式或规则。
3. 对应:指出题目中的哪个条件满足该规则。
4. 过程:有计算或状态变化时,保留关键中间步骤。
- 只要求“写出结果”的 1 分题,可能只用第 1 层。
- 要求“说明理由”的题,通常至少写到第 3 层。
- 要求计算或推导的题,需要写到第 4 层。
判断是否写够,可以做一次“删除测试”:删掉一句话后,阅卷人还能确认你的答案和依据吗?如果不能,就保留;如果能,而且该句与问题无关,就删掉。
简答题:结论和决定性判据
示例一:比较两个处理的开销
2016 年第 45 题 问:Cache 缺失和缺页处理哪个时间开销大?为什么?
不充分的写法:
缺页处理的开销大。
它给了结论,却没有完成“为什么”。
合格写法:
缺页处理的开销更大。缺页需要访问磁盘,
而 Cache 缺失只需访问主存;磁盘访问远慢于主存访问。
也可以从处理机制回答:缺页需要由软件参与处理,而 Cache 缺失主要由硬件处理。该题的评分说明明确接受这种不同于参考答案的正确理由。
这个例子说明,简答题不要求逐字复现参考答案。只要结论正确,判据能够支持结论,并且与题目场景对应,就可以形成采分点。
示例二:一句“为什么”里可能有两个动作
2015 年第 43 题 问:为什么单总线数据通路需要暂存器 T?
较弱写法:
T 用来暂存数据。
“暂存数据”没有说明为什么必须暂存,区分度不足。
更好的写法:
单总线一次只能传送一个操作数。先将一个操作数暂存在 T 中,
再由总线送入另一个操作数,ALU 才能同时获得两个不同输入。
这里的关键词是“单总线”“两个操作数”和“同时输入 ALU”。不是字多,而是因果链完整。
示例三:什么时候只写结论就够
2017 年第 43 题 的部分小问只要求最大的 n。评分说明明确写着“只要给出 n=30 即可给分”。此时写:
n=30
已经足够。若时间充裕,可以补一句范围依据帮助自查,但不能因此得出“所有 1 分题都只写结果”的结论。是否需要理由,仍由题目要求和评分点决定。
判断或论证题:反例必须能完成反驳
2009 年第 41 题 给出一种“每次走向当前最近顶点”的方法,问它能否求得最短路径;若不能,需要举例说明。
只写下面这句不够:
不能,因为局部最优不一定能得到全局最优。
它表达了方向,但题目明确要求举例。完整答案至少应包含:
结论:该方法不一定得到最短路径。
反例:给出一个带非负权值的图,并标明起点、终点和边权。
按题设贪心规则,算法依次选择的路径长度为 3;
但图中存在另一条长度为 2 的路径。因此该方法得到的不是最短路径。
一个有效反例要让人检查四件事:
- 反例满足原命题前提,例如边权非负、起点到终点存在路径;
- 题设算法在该图上会作出什么选择;
- 算法得到的结果是多少;
- 更优结果是多少,两者确实矛盾。
只画图而不标出算法路径和更短路径,会让关键反驳停留在阅卷人的推测中。
计算题:每个数字都应该有来源
示例一:Cache 命中率
2014 年第 45 题 问程序执行时指令 Cache 的命中率。
只写:
99.98%
结果虽然正确,但评分说明明确指出,没有原因和过程只能得到该问的一部分分数。
推荐写成:
6 条指令共占 6×4 B=24 B。程序从主存块首地址开始,
且 24 B<32 B,所以全部指令位于同一个主存块。
第一次取指发生 Cache 缺失,调入后其余取指均命中。
总取指次数为 1000×6,故
命中率=(1000×6-1)/(1000×6)≈99.98%。
这段答案中每一行承担不同功能:
| 行 | 暴露的采分点 |
|---|---|
6×4 B=24 B | 程序的指令空间范围 |
24 B<32 B 且从块首开始 | 所有指令位于同一主存块 |
| 第一次缺失,之后命中 | 缺失次数 |
| 命中率公式 | 最终计算 |
如果最后除法算错,前三步仍然让阅卷人看到正确思路;只写结果则没有这种余地。
示例二:中断和 DMA 的 CPU 开销
2009 年第 43 题 要求给出计算过程。中断方式的答案可以压缩成下面四步:
每次中断开销=(18+2)×5=100 个时钟周期。
每秒中断次数=0.5 MB/4 B=125000 次。
每秒中断总开销=100×125000=12.5M 个时钟周期。
CPU 时间占比=12.5M/500M=2.5%。
不要把四步合成一个无法辨认单位的长算式。分行以后,“单次开销、发生次数、总开销、占比”四个量都可以独立检查。
计算题还要注意:
- 第一次出现缩写或中间量时说明含义;
- 单位在代入前统一,尤其是 bit/B、KB/B、ns/ms;
- 近似值写
≈,不要写成严格相等; - 题目要求“至少”“最多”时,在结论中保留限定词。
推导题:保留起点、桥梁和终点
2016 年第 42 题 问:正则 k 叉树有 m 个非叶结点时,叶结点有多少个?题目明确要求给出推导过程。
只写结论:
n₀=(k-1)m+1
不能满足题目要求。一个足够短而完整的推导是:
设叶结点数为 n₀,则总结点数 n=n₀+m,树的边数为 n-1。
另一方面,m 个非叶结点的度均为 k,所以边数也等于 mk。
因此 n₀+m-1=mk,解得 n₀=(k-1)m+1。
这里包含:
起点:总结点数与边数的关系
桥梁:用两种方法计算同一个边数
终点:联立并解出待求量
参考答案采用哪一种推导并不重要。评分说明明确表示,其他正确推导方法同样给分。复习时应该记住“对哪个量进行两次计数”,而不是背整段文字。
列举题:宁缺毋滥也不是原则,精准才是原则
示例一:错误项会污染整组答案
2015 年第 43 题 要求判断哪些端点连接到控制部件的输出端。评分说明指出,答案一旦包含某些错误端点,该问不给分;答案不全则酌情给分。
这说明“把可能的都写上,总能碰到几个”并不成立。列举题应当:
- 先在草稿上逐项判断;
- 答题纸只写最终确认的集合;
- 使用清楚的分隔符,不让编号和解释混在一起;
- 若要求说明理由,再逐项对应理由。
推荐格式:
应连接的端点为:①、②、③、⑤、⑧。
不要在最终答案后面加“④可能也算”这类自我否定的内容。
示例二:不能把整个字段表抄上去
2011 年第 47 题 问 IP 分组经过路由器 R 转发时需要修改哪些首部字段。结合题目场景,应写:
必然修改:TTL、首部校验和。
由于 R 执行 NAT,还要修改源 IP 地址。
若输出链路需要分片,再修改总长度、标志和片偏移字段。
该题的评分说明特别指出,把所有 IP 首部字段全部罗列出来不给分。原因不是写得多本身有罪,而是“全部罗列”没有完成“哪些字段需要修改”的筛选。
列举题的答案应当是一个明确集合:属于集合的写出来,不属于的不要写;条件性答案要把条件一并写出。
状态变化题:不要跨过触发条件
操作系统调度、页面置换、中断和 TCP 序号题经常不是缺少最终结论,而是漏写一次状态更新。建议按下面的最小链条书写:
事件 → 触发条件 → 使用的规则 → 新状态
例如,不能只写:
P2 抢占 P1。
应该根据题目实际规则写成类似:
t=30 时 P2 到达,但题目规定只在时钟中断时检查抢占,
所以此时 P1 继续运行;到下一次时钟中断,再比较优先级并调度 P2。
这里的关键不是句式,而是区分“事件发生”和“状态立即改变”。具体的建模方法见 长题综合题实践。
算法题:思想、实现和分析必须相互对应
2017 年第 41 题 要求把表达式树输出为带必要括号的中缀表达式,包括“基本设计思想”和“C/C++ 实现”两个小问。
基本思想可以写成:
对表达式树进行中序遍历。访问非根、非叶的分支结点所代表的子表达式时,
在遍历其左子树前输出左括号,在遍历其右子树后输出右括号;
根结点和叶结点不额外加括号。
这段话应当能映射到代码:
void printExpr(BTree *root, int depth) {
if (root == NULL) return;
int isLeaf = root->left == NULL && root->right == NULL;
if (depth > 1 && !isLeaf) printf("(");
printExpr(root->left, depth + 1);
printf("%s", root->data);
printExpr(root->right, depth + 1);
if (depth > 1 && !isLeaf) printf(")");
}
算法题检查清单:
- 思想中说的遍历次序,是否与代码一致;
- 基本情况是否处理,如空树、叶结点、根结点;
- 括号、下标、循环边界是否成对或闭合;
- 题目要求的输入输出是否真的实现;
- 复杂度是否根据自己写出的算法分析,而不是背“最优复杂度”。
注释只写关键意图,不必把每行代码翻译成中文。评分说明允许其他正确算法,参考答案的代码不是唯一合法写法。
草稿和答题纸承担不同任务
草稿允许试错,答题纸负责呈现最终逻辑。
| 草稿纸 | 答题纸 |
|---|---|
| 缩写题干、试公式、画状态 | 按小问编号给出最终答案 |
| 保留被排除的可能性 | 只保留确认后的结论 |
| 可以使用个人符号 | 符号首次出现时含义明确 |
| 可以跳步供自己使用 | 关键采分步骤必须可复核 |
不要把草稿原样誊写,也不要因为草稿上“已经算过”就在答题纸只写结果。
如何使用参考答案
对完答案后,不要只标一个对勾或叉号。把参考答案拆成采分点:
题目要求:为什么缺页开销更大?
结论点:缺页开销更大。
依据点:缺页访问磁盘,Cache 缺失访问主存。
我的缺口:只写了结论,漏掉比较依据。
遇到自己的方法和参考答案不同,可以依次检查:
- 最终结论是否回答了同一个对象;
- 使用的定义和规则是否成立;
- 是否使用了题目全部相关条件;
- 中间步骤能否推出结论;
- 时间、空间或适用范围是否满足题目要求。
五项都成立,就不必为了“长得不像答案”而否定自己的解法。真题中的评分说明多次明确接受其他正确推导、算法或表述。
书写复盘模板
每周选几道综合题,不重算整题,只复盘落笔:
题目年份/题号:
小问动词:写出 / 说明 / 计算 / 推导 / 设计
预计采分点:
我的答案:
遗漏的依据或步骤:
可以删除的无关内容:
单位、对象、条件是否准确:
压缩后的合格答案:
“压缩后的合格答案”最重要。它既不能只有结果,也不应照抄长篇解析,而应保留足以得分和复核的最短逻辑链。