ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CSPJ第一轮选择题提分:2012普及组初赛卷题型拆解

CSPJ第一轮选择题提分:2012普及组初赛卷题型拆解

考CSPJ第一轮的人大多有过这样的体验:花了一晚上刷阅读程序和完善程序,回头一看选择题错了七八道,每题1.5分,十来分就这么没了,而这十来分往往就是"过线"和"差一点"的区别。我这几年带学生复盘,发现一个挺反直觉的结论——选择题不是"背多分"的题,而是"结构分"的题。真正拉开差距的不是谁知道的知识点多,而是谁能在考场上把20道选择题按题型拆成几类、每类用固定打法在40秒内出结果。2012年这套普及组初赛卷子,我前后用过不下十遍,它最大的价值不在于年份久远,而在于题型分布特别"正":计算机基础、进制与编码、算法与数据结构三条线各占约三分之一,几乎没有偏题怪题,拿来当CSPJ初赛选择题训练的"标尺卷"非常合适。下面我就把这套卷子拆开揉碎,讲清楚每一类题该怎么想、怎么算、怎么防错,以及一套卷子到底该怎么用才不浪费。

1. 2012年这套卷子的题型骨架:先看清结构再动手

很多人拿到卷子第一反应是从第1题开始顺着做,做完对答案,错的看解析,然后换下一套。这套流程最大的问题是:你记下的是20个孤立的知识点,而不是4到5种可复用的解题路径。所以我在带人刷这套卷子之前,会先花十五分钟只做一件事——把题目按"解题动作"分类,而不是按"知识点"分类。

1.1 按"解题动作"而不是"知识章节"分类

知识点分类是这样的:计算机基础、进制转换、数据结构、算法、网络。这种分法看着整齐,但对考场没有指导意义,因为"数据结构"下面既有需要算的(节点数、边数),也有需要判断的(稳定性、复杂度),两者的解题动作完全不同。

我习惯分成五类动作:

  • 纯记忆调用:看到就能答,比如存储单位换算、常见输入输出设备、协议所属层次。这类题的准备方式是背卡片,考场动作是"秒答不纠结"。
  • 规则套算:有明确公式或步骤,比如进制互转、补码求值、树的节点与边关系、完全二叉树高度。考场动作是"套流程、写中间步骤"。
  • 辨析判断:两个概念长得像,要挑出差别,比如顺序存储与链式存储、编译与解释、栈与队列的适用场景。考场动作是"找反例"。
  • 手工模拟:给一小段伪代码或递推式,手算几步得出结论,比如递归调用次数、简单循环的累加结果。考场动作是"列表格、逐行推"。
  • 估算排除:选项里有明显数量级差异或明显违背常识的,直接排掉。考场动作是"先排两个,再算一个"。

按这五类过一遍,你会发现这套卷子里"纯记忆调用"大概占5到6题,"规则套算"占5题左右,"辨析判断"4题上下,"手工模拟"3题左右,剩下的是估算排除能解决的。分完类你就知道时间该怎么分配了:记忆题不要超过40秒,套算题给90秒,手工模拟题留足2分钟,剩下的时间回头检查。

1.2 为什么2012年的卷子到今天还值得反复刷

有人会问,十多年前的卷子,计算机基础部分是不是过时了?确实有这个问题——当年考的某些硬件参数、存储介质类型,放到今天已经不太贴切。但我依然推荐它作为训练起点,理由有三个。

第一,进制、编码、补码、树与图的基本关系、排序查找的复杂度与稳定性,这些内容十几年没变过。它们是计算机科学的底层约定,不是某一年的技术热点。这套卷子在这几块上的覆盖非常完整,属于"一次刷透、长期受益"。

第二,它的难度曲线平缓,适合建立信心。有些年份的卷子前面几题就开始挖坑,做下来心态容易崩。2012年这套题的难度是渐进式的,前段友好、中段有区分度、后段靠阅读理解和细心,适合刚接触CSPJ第一轮的人用来找手感。

第三,它是最好的"错题归因样本"。因为题目不偏,你错在哪一类,基本就代表你哪一块方法没建立起来。如果错的是偏题怪题,归因价值反而低。

提示:如果你手上这套卷子没有配套答案,先别急着找。做完之后自己动手把每道题的"解题动作"标出来,再去找答案对,这个过程中的自我判断本身就是训练的一部分。

1.3 一套卷子的正确打开方式:三遍法

我带人刷这套卷子,从来不是"做一遍、对答案"就完事,而是三遍。

第一遍叫裸做,限时35分钟只做选择题部分(真实考场上20道选择题建议控制在25到30分钟内完成,留时间给后面的阅读程序)。裸做的目的是暴露真实水平,不允许翻书、不允许查笔记、不允许"这题我记得好像是"。

第二遍叫归因,不看解析,只看对错。对的题也要过一遍,问自己"我是真会还是蒙对的";错的题分成四类——不会、会但算错、会但看错题、蒙错。这四类的处理方式完全不同,后面第5节会详细讲。

第三遍叫重做,隔三到五天,把错题和"蒙对题"单独抽出来再做一次。如果第二次还错,说明这块不是"忘了",是"没建立正确的解题模型",需要回到方法层面重新捋,而不是再多刷题。

三遍下来,一套卷子的利用率大概是别人的三倍。这一点我特别想强调:刷题的收益不在数量,在于同一道题上你能榨出多少信息。

2. 计算机基础题:把"背"变成"查表",把"查表"变成"排除"

这类题在整套卷子里是"性价比最高"的部分——知识点有限、重复率高、不需要计算。但恰恰是这部分,很多人错得莫名其妙,原因就两个字:纠结。看到两个选项都眼熟,就开始回忆课本,越回忆越模糊,最后靠感觉选,选完还不放心,回头又改一遍,改成错的。

我的建议是把这部分彻底"工具化":不做回忆,只做查表和排除。

2.1 存储与硬件题的固定套路

存储相关的题,考点集中在三个方向:单位换算、存取速度层级、易失与非易失。单位换算那几道,只要记住二进制前缀(Ki、Mi、Gi)是1024进位、十进制前缀(k、M、G)是1000进位,剩下的就是简单的乘除。这里有个坑:题目里说"1KB"时,如果上下文是存储容量,通常按1024算;如果上下文是传输速率,往往按1000算。所以做题时先看题目问的是"容量"还是"速率",这一个动作能排掉一半的错选项。

存取速度层级那道题,本质是问"哪个离CPU更近"。顺序大致是:寄存器 → 高速缓存 → 内存 → 固态存储 → 机械硬盘 → 外部介质。近的快、贵的、容量小的,远的慢的、便宜的、容量大的。这个顺序背后的逻辑是"速度与成本的折中",理解了这个逻辑,即使选项里出现你没见过的介质,也能靠"它大概是哪一档"推出来。

易失性那道题简单但要小心措辞。"断电后数据丢失"的是内存类和缓存类;"断电后数据保留"的是外存类。有些题会故意写成"断电后需要重新加载",这个说法其实也是在描述易失性,别被绕进去。

2.2 网络与协议:只考那几个点,别自己加戏

网络题在这套卷子里占比不高,但出题角度很固定。我把常见考点列一下:

考点常见问法记忆抓手
分层模型某协议属于哪一层由下往上:物理、链路、网络、传输、应用
地址与端口哪个是合法地址、端口范围地址四段、每段0到255;端口0到65535
域名与解析域名到地址的转换过程先本地缓存,再逐级查询
传输方式面向连接还是无连接有握手、有序到达的是面向连接

这几道题的正确率,很大程度上取决于你会不会"用生活场景去锚定"。比如面向连接与无连接,我用的是寄快递的类比:挂号信要签收、有单号、按顺序到,对应面向连接;普通明信片扔进邮筒就走,不保证到达也不保证顺序,对应无连接。这个类比一旦建立,题目怎么变你都不会选反。

还有一个容易被忽视的点:题目问"以下说法错误的是"时,往往三个正确选项都是常识性描述,只有一个是偷换概念的。比如把"传输层负责端到端"偷换成"传输层负责路由选择"(后者是网络层的事)。所以做这类题,我的动作是先扫一遍四个选项找"偷换",而不是逐个验证正确性。

2.3 我的记忆卡片做法

计算机基础这块,我不建议看整章教材,效率太低。我的做法是做成"一问一答"的小卡片,每张卡片一个问题,背面一句话答案,外加一个"为什么"。

具体做法是这样:把所有做错的基础题,改写成一句提问。比如错了一道关于缓存的题,卡片正面写"高速缓存的作用是什么",背面写"缓解CPU与内存的速度差,存放近期常用数据"。关键是背面那句话要短,短到你扫一眼就能记住,长了反而记不住。

卡片数量控制在30张以内。超过30张说明你在把边角知识当重点,方向就偏了。每张卡片每周过一遍,过的时候不是"读",而是"遮住背面自己答",答不出来的挑出来放"重点堆",答得出来的放"冷却堆",一周后再混在一起过。这套方法看起来笨,但它是唯一能把"见过"变成"记得"的办法。

注意:基础题的准备有一个心理陷阱——因为内容简单,很多人不愿意花时间,觉得"临考再看"。但考场上的时间是稀缺资源,基础题省下来的每一分钟,都能给后面的手工模拟题。这笔账要提前算清楚。

3. 进制与编码:手算速度才是真正的分水岭

这是整套卷子里最能拉开时间的部分。同一道进制转换题,熟练的人30秒出答案,不熟练的人要写满半页草稿还容易错。差距不在智商,在方法。

3.1 二、八、十六进制互转:只记"分组",不记"除法"

十进制转其他进制用短除法,这个必须会,但考场上用得不多。真正高频的是二、八、十六进制之间的互转,而这三种进制之间有一个极大的便利:它们都是2的幂次。

具体做法是分组:

  • 二进制转八进制:从右往左,每3位一组,不足补0,每组换成0到7。
  • 二进制转十六进制:从右往左,每4位一组,不足补0,每组换成0到15。
  • 反过来,八进制转二进制就是把每一位拆成3位,十六进制转二进制就是每一位拆成4位。

举个例子,把二进制110101110转成十六进制:

原数: 1 1010 1110 补齐: 0001 1010 1110 分组转换: 1 A E 结果: 0x1AE

同样这个数转八进制:

原数: 110 101 110 分组转换: 6 5 6 结果: 0o656

这套方法的优势是没有除法、没有余数、不涉及进位,纯粹是查表替换。十六进制的A到F对应10到15,这张表要背到条件反射,因为它出现的频率太高了。

我见过不少人在这类题上失分,不是因为不会转,而是因为方向搞反了——从右边分组还是从左边分组。记住一句话:整数部分从右往左分组,小数部分从左往右分组。小数部分如果位数不够,补0补在右边。

3.2 补码:从定义推,不要背结论

补码是失分重灾区。很多人背的是"正数补码是本身,负数补码是取反加一",背得挺熟,但一遇到"给定补码求原值"或者"两个补码相加判断溢出",就懵了。

我的建议是回到定义去理解。补码的本质是把减法变成加法。在n位二进制下,一个负数 -x 的补码,等于 2的n次方 减去 x。这个定义比"取反加一"更本质,因为它直接告诉你补码的数学含义。

用例子说:8位下求 -5 的补码。

定义法: 2^8 - 5 = 256 - 5 = 251 = 11111011 取反法: 5 = 00000101 取反 = 11111010 加一 = 11111011

两种方法结果一致,但定义法在判断溢出时更有用。判断溢出的经典规则是:两个同号数相加,结果符号变了,就是溢出。为什么?因为同号相加的结果绝对值变大,如果超出了n位能表示的范围,符号位就会被"顶"掉。理解了这一点,你就不需要去背"最高位进位与次高位进位是否相同"这种绕口的判据了。

再比如"给定补码 11110110,求其真值",我的做法是先看符号位是1,说明是负数,然后用 2的8次方 减去这个补码值,得到绝对值:

补码值 = 11110110 = 246 绝对值 = 256 - 246 = 10 真值 = -10

一步到位,不用取反加一倒腾两遍。这个方法我在课上讲过很多次,学生反馈是"算得慢但不会错",而取反加一是"算得快但容易在加一那步出错"。考场上,稳比快重要。

3.3 字符编码与校验:理解"为什么需要它"

字符编码题通常考两类:一是某种编码用多少位表示一个字符,二是给定编码求字符数量。这类题的坑在于"位"和"字节"的单位混用。看清楚题目问的是bit还是Byte,1Byte等于8bit这个换算在题干里经常被故意省略。

校验位的题看着吓人,其实逻辑很朴素:在数据后面附加若干位,使得某种统计规律成立,接收方据此判断是否出错。奇偶校验是让1的个数保持奇数或偶数;更复杂的校验是让某几位的和满足特定关系。这类题的正确做法不是去背具体算法,而是照着题目给的规则,把数据代进去算一遍。题目说"偶校验",那你就数1的个数,是奇数就在校验位补1,是偶数就补0,就这么简单。

有一点要提醒:校验位能发现错误,但通常不能纠正错误(除非是纠错码,比如海明码)。如果选项里出现"可以纠正一位错误"这种表述,要看清楚题目问的是哪种校验方式,不要一概而论。

4. 算法与数据结构题:不写代码也要会"读"和"推"

这部分是整套卷子里最能体现思维方式的。它不要求你会写代码,但要求你能看懂别人写的代码,或者根据定义推出结论。很多人在这里失分,原因是"想太多"——试图用完整的算法思维去解一道只需要三步模拟的小题。

4.1 排序与查找:稳定性与复杂度必须做成一张表

排序算法的对比是必考点。这张表我建议直接背下来,考场上看一眼就能选:

算法平均时间最坏时间空间稳定性
冒泡排序O(n²)O(n²)O(1)稳定
插入排序O(n²)O(n²)O(1)稳定
选择排序O(n²)O(n²)O(1)不稳定
归并排序O(n log n)O(n log n)O(n)稳定
快速排序O(n log n)O(n²)O(log n)不稳定
堆排序O(n log n)O(n log n)O(1)不稳定

背这张表有个技巧:稳定的是"相邻交换"和"分治合并"这两类。冒泡和插入都是相邻元素比较后交换,不会把相隔很远的相等元素调换顺序,所以稳定;归并是先分后合,合并时遇到相等元素优先取左边的,所以也稳定。选择排序会做长距离交换,快速排序的分区过程会打乱相对顺序,堆排序的调整过程更是跨层移动,所以这三个都不稳定。

理解了这个"为什么",即使考试时忘了某一格,也能推出来。这比死记硬背靠谱得多。

查找部分主要考二分查找。要记住两个前提:数据必须有序,以及每次能排除一半。由此推出的比较次数上限是 log₂n 向上取整。如果题目给1000个元素,问最多比较几次,就是10次(因为2的10次方是1024,大于1000)。

4.2 树与图:节点、边、度的三条铁律

这部分有几条公式是必须刻在脑子里的:

  • 二叉树中,度为0的节点数等于度为2的节点数加1。即 n₀ = n₂ + 1。
  • 一棵有n个节点的树,边数是 n - 1。
  • 完全二叉树中,编号为i的节点,左孩子编号是 2i,右孩子是 2i+1,父节点是 i/2 取整。

第一条公式的推导很有意思,值得花两分钟理解:设节点总数为n,则 n = n₀ + n₁ + n₂(度为0、1、2的节点数)。再看边数,每个节点(除根)都有一条入边,所以边数是 n - 1;从"出边"角度看,度之和等于边数,即 n₁ + 2n₂ = n - 1。两式联立,把 n 消掉,就得到 n₀ = n₂ + 1。

这个推导过程我建议每个人都手推一遍。因为考试时可能会换个问法,比如"已知叶子节点数,求度为2的节点数",或者"已知总节点数和度为1的节点数,求叶子数"。如果你只背结论,换个问法就卡住了;如果你会推,怎么问都能现推。

图的部分主要考两个概念:有向图与无向图的边数上限,以及连通性与生成树。n个顶点的无向完全图有 n(n-1)/2 条边,有向完全图有 n(n-1) 条边。无向连通图最少有 n-1 条边(就是一棵树),最多有 n(n-1)/2 条边。这几个数字之间的关系搞清楚,判断"某图是否连通"这类题就不难了。

4.3 手工模拟递归:画表格,别在脑子里跑

给一段递归伪代码问调用次数或者输出结果,这是很多人的噩梦。在脑子里"跑"代码,跑到第三层就乱了。

我的方法很土但极其有效:画一张表,每一行记录一次调用,列出参数、返回值、以及它依赖的下一层调用。以经典的斐波那契递归为例:

调用 f(4) ├── f(3) │ ├── f(2) │ │ ├── f(1) → 1 │ │ └── f(0) → 0 │ └── f(1) → 1 └── f(2) ├── f(1) → 1 └── f(0) → 0

画成树之后,调用次数一目了然:f(4)这棵树上一共有9个节点,说明调用了9次。返回值从叶子往上加,也能一层层算出来。

这个方法的额外好处是,它能让你看出重复计算在哪里。上面这棵树里 f(2) 被算了两次,f(1) 被算了三次。如果题目问"这段代码的时间复杂度为什么是指数级",答案就在这里——重复子问题。用备忘录把算过的结果存下来,复杂度就降到线性。这个知识点在选择题里经常以"以下哪种方法可以优化"的形式出现。

提示:模拟题最忌讳的是"跳步"。哪怕你觉得某几步很明显,也要一行一行写下来。选择题没有过程分,但过程写下来能保证结果对,而结果对了才有分。

5. 一套卷子的训练节奏:从"做完"到"用透"

前面四节讲的是题目本身怎么解,这一节讲的是怎么把一套卷子用出三套的效果。这部分内容在很多资料里是缺失的,但我认为它比具体知识点更重要——因为知识点可以补,方法不对则是白费力气。

5.1 限时模拟要模拟"真实压力"

限时35分钟做20道选择题,这个时间设置是有讲究的。真实考场上,选择题之后还有问题求解、阅读程序、完善程序三大部分,总共两个小时的考试,选择题最多只能占30分钟左右,否则后面会崩。

但限时不只是为了练速度,更重要的是练决策。真实考场上你一定会遇到卡住的题,这时候你是继续啃还是先跳过?这个决策能力只能在限时训练中培养。

我给学生定的规则是"40秒法则":一道题读两遍题干、扫一遍选项,如果40秒内没有明确的解题路径,立刻标记跳过。跳过的题在最后统一回头看,那时候心态放松,往往一眼就能看出思路。这个规则听起来简单,但真正执行起来需要克制——人天生不愿意"放弃",哪怕只是暂时放弃。

还有一个小细节:限时训练要用纸质卷子和笔,不要用电子版。真实考场是纸笔,眼睛在纸面上的搜索路径和在屏幕上完全不同,翻页、标记、打草稿的手感也不同。这个差异在平时训练中被忽略,考场上就会变成额外的认知负担。

5.2 错题归因的三栏法

对完答案之后,大部分人的动作是"看解析,哦原来是这样,下一题"。这个动作的问题是,它只解决了"这道题",没有解决"这类题"。

我的做法是准备一张表,分三栏:

栏目填什么用途
错因不会 / 算错 / 看错题 / 蒙错决定后续处理方式
动作这道题应该用哪类解题动作检验自己的分类是否准确
一句话这类题的通用打法,不超过30字形成可复用的肌肉记忆

"一句话"这一栏是关键,也是最难写的。因为它要求你把一道具体的题抽象成一条规则。比如错了一道补码求值的题,一句话不能写"补码要取反加一",那还是具体方法;应该写"求补码真值,先用2的n次方减,比取反加一稳"。这条规则下次遇到同类题就能直接用。

四类错因的处理方式完全不同:

  • 不会:说明知识有缺口,回到教材或笔记补这一块,补完立刻找三道同类题验证。
  • 算错:说明方法有问题或者不熟练。方法有问题就换方法,不熟练就专项练十道。
  • 看错题:这类最冤枉,但也最好解决——养成"读题时圈关键词"的习惯,特别是"以下错误的是""最多""至少""不包括"这些词。
  • 蒙错:说明知识模糊,介于会和不会之间。处理方式是把它当"不会"处理,别放过。

我特别想强调"看错题"这一栏。统计下来,中低分段的失分里,看错题能占到三成。这个比例高得惊人,但很少有人专门去治。我自己的办法是做题时用笔在题干上划,凡是出现"不正确""除外""最少"这类词,画个圈。这个动作花不到两秒,但能救回好几分。

5.3 三个高频坑,几乎人人踩过

第一个坑是在进制题上过度验算。算完一遍不放心,再算一遍,结果第二遍算错了,反而把对的改成错的。我的建议是:第一遍算的时候把中间步骤写清楚,写清楚了就不用验算;如果非要验算,换一种方法验(比如用除法验分组法),不要重复同一个动作。

第二个坑是把"复杂度"和"实际速度"混为一谈。题目问"哪种排序最快",如果选项里同时有快排和归并,要看清前提——平均情况下快排常数小,实际更快;但如果题目强调"最坏情况"或者"稳定性",答案就变了。看到一个"最"字,先找前提条件。

第三个坑是在阅读量大的题上耗太久。有些题的题干长得像小作文,读完三分钟过去了。这类题的正确策略是先看问题,再回头读题干——带着问题读,能过滤掉大量无关信息。这个技巧在选择题的后半段特别管用,因为那时候时间紧、心态急,逐字读是最亏的。

5.4 从一套卷子到一类卷子:怎么迁移

刷完2012年这套,下一步不是马上去刷2013年,而是问自己一个问题:这套卷子里的五类解题动作,我哪一类最弱?找到最弱的那一类,专门找同类题集中突破,而不是继续成套成套地刷。

成套刷的好处是全面,坏处是效率低——你花两小时做的20道题里,可能只有5道对你有提升价值。集中突破则相反,半小时能解决一类问题。

我的建议节奏是这样:先用两到三套完整卷子做"诊断",找出薄弱环节;然后针对薄弱环节做专项训练,每个专项20到30道题;专项练完再回到完整卷子做"验收"。这个循环走两到三轮,选择题的稳定得分就能上一个台阶。

具体到2012年这套,如果让我给一个诊断模板,大概是这样的:

板块题量估计目标正确率未达标时的补救
计算机基础5到6题全对记忆卡片,30张以内
进制与编码5题全对分组法专项练20道
算法与数据结构5题对4题公式推导+模拟表练习
综合判断4到5题对3题读题圈词+排除法训练

这个表格不是标准答案,每个人的情况不同,但它能给一个参照系:如果某个板块的正确率明显低于目标,就说明那一块需要专门花时间,而不是继续整套刷。

最后分享一个我自己用了很多年的小习惯:每套卷子做完,在卷子首页写一行字,记录"这套题我最大的收获是什么",一句话就够。攒到十套的时候回头看,你会发现这十句话连起来,就是你自己总结出来的一套方法论,比任何资料都贴合你的实际情况。2012年那套卷子首页我写的是"进制题不验算,补码用减法",到现在还适用。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进