1. 这份模拟卷到底解决什么问题
每年一到七八月份,后台就会涌进来一堆私信,问的都是同一件事:初赛到底怎么准备。问的人里面,有刚学完循环和数组的初一学生,也有带了几年竞赛班、想找一套靠谱题给学生练手的教练。大家卡的点其实高度一致——知识点好像都学过,但一上考场就发现,题目问法跟平时写的代码完全不是一回事。
CSP-J 初赛的题型结构这几年趋于稳定,但细节一直在微调。2026 年的这份模拟卷 1,就是按照近三年真题的命题惯性、知识点分布和难度梯度来设计的。它不追求偏题怪题,而是把重心放在那些“每年都考、但每年换着花样考”的核心考点上:进制转换、逻辑运算、数据结构性质、图论基础、排列组合、复杂度估算,以及程序阅读和代码填空这两块分值大头。
这份卷子适合谁?如果你正在准备 2026 年的 CSP-J 初赛,已经过了一遍基础语法和简单算法,但还没做过完整的套卷,那它正好用来做第一次全真模拟。如果你已经刷过几套真题,想再找一套难度接近、解析足够细的卷子来查漏补缺,它同样能用。教练拿去做课堂测验或者集训摸底,也是合适的——题目区分度做得比较清楚,基础题、中档题、拉分题的比例大致是 5:3:2。
我先把这份卷子的整体结构摆出来,后面再逐块拆解。
| 题型 | 题量 | 分值 | 建议用时 |
|---|---|---|---|
| 单项选择题 | 15 | 30 | 20 分钟 |
| 阅读程序题 | 3 | 40 | 40 分钟 |
| 完善程序题 | 2 | 30 | 30 分钟 |
| 合计 | 20 | 100 | 90 分钟 |
这个分值和题量是参照近几年真题的常见配置来的。阅读程序和完善程序加起来占了 70 分,这个比例说明一件事:初赛考的不是你背了多少知识点,而是你能不能读懂一段代码在干什么、能不能把缺失的逻辑补上。很多同学选择题做得不错,一到阅读程序就崩,根本原因不是知识不够,而是没有养成“逐行跟踪变量”的习惯。
提示:做这份卷子的时候,务必按 90 分钟计时,中途不要查资料、不要翻笔记。模拟卷的价值在于暴露问题,而不是刷出一个好看的分数。
2. 单项选择题的考点分布与解题逻辑
选择题只有 15 道,但覆盖的面很广。我把它们按知识点归了个类,方便你对照自己的薄弱环节。
2.1 进制与编码:每年必考,但坑都在细节里
进制转换是初赛的常客,几乎每年都有一到两道。这份卷子里涉及进制的题目有两道,一道考二进制与十进制的互转,一道考补码表示。很多同学觉得进制转换是送分题,结果一考补码就翻车。
补码的核心逻辑其实就一句话:正数的补码等于原码,负数的补码等于其绝对值的二进制按位取反再加一。听起来简单,但实际操作时容易在“位数”上出错。比如 8 位补码表示 -5,先写出 5 的二进制 00000101,按位取反得到 11111010,再加一得到 11111011。如果你忘了固定位数这个前提,直接对 101 取反加一,结果就完全错了。
注意:补码题目一定要先确认字长。题目没说字长的时候,通常默认是 8 位或者 16 位,看题目上下文。
2.2 逻辑运算与位运算:优先级是最大的坑
逻辑运算和位运算的题目,失分点几乎全在优先级上。很多同学写代码的时候习惯加括号,所以对优先级不敏感,但选择题偏偏就考这个。
这份卷子里有一道题是这样的:给出一个表达式,里面混合了与、或、异或、取反和移位,问结果是多少。做这种题的唯一可靠方法,就是按照优先级表一步步拆。我一般建议学生先在心里默念一遍优先级顺序:取反 > 移位 > 与 > 异或 > 或。同级运算从左到右。
位运算还有一个高频考点是“判断奇偶”和“交换变量”。用 n & 1 判断奇偶,用异或交换两个数,这些技巧在阅读程序题里经常出现。如果你不熟悉,读代码的时候就会卡住。
2.3 数据结构性质:别只记结论,要理解为什么
数据结构的选择题通常考性质判断,比如“以下关于二叉树的说法正确的是”。这类题看着简单,但选项里往往藏着一些似是而非的表述。
举个例子:完全二叉树中,如果节点数为 n,那么叶子节点的数量是多少?这个结论很多同学背过,但一到具体数字就容易算错。更稳妥的做法是画一个小的完全二叉树,数一数,验证一下公式。比如 n=5 的时候,叶子节点是 3 个;n=6 的时候,叶子节点也是 3 个。多试几个,规律就清楚了。
栈和队列的题目也是同理。栈的特点是后进先出,队列是先进先出,这个谁都知道。但题目往往会给出一个入栈序列,问哪个出栈序列是不可能的。做这种题,我习惯用模拟法:拿一张纸,按照选项的顺序试着操作,看能不能走通。比纯推理靠谱得多。
2.4 图论基础:概念要清,计算要准
图论在初赛里主要考概念和简单计算,比如完全图的边数、树的边数与节点数的关系、度的计算等。
完全图 Kn 的边数是 n(n-1)/2,这个公式要记牢。树的边数等于节点数减一,这个也是基础。但题目有时候会绕一下,比如“一个无向连通图有 10 个节点,至少有多少条边”,答案就是 9,因为树是最少的连通图。
还有一类题考的是“度的总和等于边数的两倍”,这个性质在计算题里经常用到。比如已知所有节点的度,求边数,直接用度数和除以二就行。
2.5 排列组合与概率:分清排列还是组合
排列组合的题目,最大的坑是分不清什么时候用排列、什么时候用组合。简单判断方法:如果顺序重要,就是排列;如果顺序不重要,就是组合。
这份卷子里有一道题考的是“从若干人中选若干人排成一排”,这就是典型的排列问题。另一道考的是“从若干人中选若干人组成一个小组”,这就是组合。题目里通常会有“排列”“顺序”“依次”这些词提示你用排列,有“选出”“组合”“小组”这些词提示你用组合。
概率题一般考的是古典概型,核心是算清楚总的情况数和满足条件的情况数。注意“至少”“至多”这类词,往往需要用补集的思想来简化计算。
2.6 复杂度分析:看循环嵌套的层数和范围
复杂度分析的题目,通常给出一段伪代码,问时间复杂度是多少。做这种题,关键是看循环的嵌套层数和每层循环的范围。
如果是一个 for 循环从 1 到 n,复杂度就是 O(n)。两层嵌套都是 1 到 n,就是 O(n²)。但如果内层循环的范围依赖于外层变量,比如 for i=1 to n,for j=1 to i,那总次数就是 n(n+1)/2,复杂度仍然是 O(n²),但系数是 1/2。
还有一类题考的是递归的复杂度,比如斐波那契数列的朴素递归实现,复杂度是指数级的。这个要能识别出来。
3. 阅读程序题的拆解方法
阅读程序题是初赛的重头戏,三道题共 40 分。很多同学在这块失分严重,不是因为看不懂语法,而是因为没有掌握正确的阅读方法。
3.1 先看整体结构,再逐行跟踪
拿到一段阅读程序,不要上来就从第一行开始逐行读。我通常的做法是分三步:
第一步,快速扫一遍代码,看它有几个函数、主函数在哪里、大概在做什么。这一步不需要理解每一行,只需要建立整体印象。
第二步,找到输入部分,看看程序接收什么数据。然后从主函数开始,按照执行顺序逐行跟踪。跟踪的时候,在草稿纸上画出变量表,每执行一行就更新变量的值。
第三步,遇到循环的时候,不要试图在脑子里跑完所有迭代。先跑前两三次,找出规律,然后直接跳到循环结束时的状态。
这个方法听起来笨,但实测下来非常稳。我带过的学生里,凡是老老实实画变量表的,阅读程序的正确率都能稳定在 70% 以上。
3.2 函数递归:画出调用树
阅读程序里经常出现递归函数。递归的难点在于调用栈的展开和回溯,光在脑子里想很容易乱。
我的建议是画出调用树。比如一个计算阶乘的递归函数,从 f(5) 开始,画出 f(5) 调用 f(4),f(4) 调用 f(3),一直到 f(1)。然后在回溯的时候,把每层的返回值标在树上。这样整个过程一目了然。
这份卷子里有一道题涉及递归求组合数,用的就是杨辉三角的递推关系。如果你能画出调用树,就能清楚地看到哪些子问题被重复计算了,也能理解为什么加个记忆化数组就能把复杂度降下来。
3.3 指针与数组:画内存图
指针和数组的题目,最容易出错的地方是下标越界和指针偏移。做这类题,我习惯画一个简单的内存图,把数组的每个元素和对应的下标标出来,然后用箭头表示指针的指向。
比如 int a[5] = {1,2,3,4,5}; intp = a; 那么 p 指向 a[0],p+1 指向 a[1],(p+2) 就是 a[2] 的值。这些看起来简单,但在复杂的题目里,指针可能会被重新赋值、可能会和数组下标混用,画图能帮你避免很多低级错误。
提示:阅读程序题里,如果看到指针操作,先在草稿纸上把数组和指针的关系画清楚,再开始跟踪执行。
3.4 字符串处理:注意边界和终止符
字符串处理的题目,坑主要在边界条件上。比如字符串的结束符 '\0',很多同学在计算字符串长度或者做字符串拼接的时候会忽略它。
这份卷子里有一道题考的是字符串反转,用的是双指针法。左指针从开头出发,右指针从末尾出发,交换两个位置的字符,然后向中间靠拢。这个算法的关键是右指针的初始位置应该是 strlen(s)-1,而不是 strlen(s)。如果你写成 strlen(s),就会把 '\0' 也交换进去,结果就错了。
还有一类题考的是字符串的字典序比较,这个要理解 ASCII 码的顺序。大写字母的 ASCII 码比小写字母小,数字的 ASCII 码比字母小。这些在比较的时候都会影响结果。
4. 完善程序题的填空策略
完善程序题两道,共 30 分。这类题的特点是:给你一段有缺失的代码,让你从选项中选出正确的填空。它考的不是你能不能从零写出代码,而是你能不能理解代码的逻辑,把缺失的部分补上。
4.1 先通读全文,理解算法意图
做完善程序题,最忌讳的是上来就看第一个空。正确的做法是先通读整段代码,搞清楚它在做什么。是排序?是查找?是动态规划?还是图论算法?
理解了算法意图之后,再去看每个空应该填什么。比如你识别出这是一段二分查找的代码,那么中间那个空大概率是更新左右边界的,左边界的更新通常是 mid+1,右边界的更新通常是 mid-1。
4.2 关注变量命名和注释
完善程序题里的变量命名通常是有意义的,比如 left、right、mid、count、sum 这些。注释也会给出一些提示。这些信息能帮你快速理解代码的意图。
如果代码里出现了 f[i] = f[i-1] + f[i-2] 这样的式子,那基本可以确定是在求斐波那契数列或者类似的递推关系。如果出现了 dp[i][j] = max(dp[i-1][j], dp[i][j-1]),那大概率是动态规划求最长公共子序列或者类似的问题。
4.3 代入选项验证
当你对某个空不确定的时候,可以把选项逐个代入,看看哪个能让代码逻辑通顺。这个方法虽然笨,但在考场上非常有效。
代入的时候要注意两点:一是语法要正确,比如括号要匹配、分号不能少;二是逻辑要正确,代入之后程序的输出要符合预期。
这份卷子里有一道完善程序题考的是快速排序的 partition 过程。其中一个空是 while 循环的条件,选项里有 i < j、i <= j、i < j && a[i] < pivot 等。如果你理解 partition 的逻辑,就知道这个循环的作用是找到第一个大于等于 pivot 的元素,所以条件应该是 i < j && a[i] < pivot。
4.4 注意边界条件和特殊输入
完善程序题里经常有一两个空是处理边界条件的。比如数组为空、只有一个元素、所有元素相同这些情况。这些空往往容易被忽略,但恰恰是区分高分和低分的关键。
我的建议是,做完之后,用几个特殊的输入在心里跑一遍。比如输入是空、输入只有一个元素、输入已经有序、输入完全逆序。如果这些情况下代码都能正确工作,那你的填空大概率是对的。
5. 常见失分点与避坑清单
带了这么多届学生,我发现初赛失分的地方其实高度集中。下面这张表是我根据历年学生的错题统计整理出来的,你可以对照着检查自己有没有这些问题。
| 失分点 | 典型表现 | 避坑方法 |
|---|---|---|
| 补码计算 | 忘记固定字长,直接对绝对值取反加一 | 先确认字长,再按步骤计算 |
| 逻辑运算优先级 | 凭感觉判断,不按优先级表拆解 | 默念优先级顺序,必要时加括号 |
| 完全二叉树叶子数 | 死记公式,遇到具体数字算错 | 画小例子验证,n=5、n=6 各试一次 |
| 出栈序列判断 | 纯推理,不模拟 | 拿纸画栈,按选项顺序模拟操作 |
| 排列组合混淆 | 分不清顺序是否重要 | 看题目关键词,排列有顺序,组合无顺序 |
| 复杂度分析 | 只看循环层数,忽略循环范围 | 计算总执行次数,再取最高阶 |
| 递归跟踪 | 在脑子里跑,不画调用树 | 画调用树,标出每层返回值 |
| 指针偏移 | 不画内存图,凭感觉算 | 画数组和指针关系图,标出下标 |
| 字符串边界 | 忽略 '\0',右指针初始位置错误 | 右指针从 strlen(s)-1 开始 |
| 完善程序填空 | 上来就填,不通读全文 | 先理解算法意图,再逐空填写 |
这张表里的每一条,都是真实学生在考场上踩过的坑。你不需要全部避免,但至少要对自己容易犯的那几条保持警惕。
注意:模拟卷做完之后,不要只看分数。把错题对应的知识点找出来,回到教材或者笔记里重新过一遍,这才是模拟卷最大的价值。
6. 从模拟卷到真题的衔接建议
模拟卷做得再好,最终还是要上真题考场。这两者之间有一个衔接的问题,我分享几个自己的经验。
第一,模拟卷的难度通常比真题略高一点。这是故意的,目的是让你在平时练习的时候就适应更高的强度。所以如果你模拟卷考了 70 分,真题大概率能考到 75 到 80 分。不要因为模拟卷分数低就灰心。
第二,真题的命题风格和模拟卷会有细微差别。真题更注重知识点的覆盖广度,模拟卷可能更注重某些重点的深度。所以做完模拟卷之后,一定要把近五年的真题都过一遍,感受一下真实的命题节奏。
第三,真题里经常出现一些“往年考过、今年换个问法”的题目。比如 2023 年考了某个知识点,2024 年可能换一个角度再考一次。所以做真题的时候,不要只记答案,要理解背后的知识点。
第四,考前一周不要再做新题了。把之前做过的错题翻出来,重新做一遍,确保每一道错题都真正搞懂了。这比做十套新卷子都管用。
7. 答案与解析的使用方式
这份模拟卷附带了详细的答案和解析。但我要提醒一句:解析不是用来“看”的,是用来“对照”的。
正确的使用方式是:先自己做一遍,做完之后对答案。对于做错的题,先不要看解析,自己再想一遍,看看能不能想通。如果想通了,再看解析验证自己的思路。如果想不通,再看解析,看看自己卡在哪一步。
对于做对的题,也不要完全跳过。快速扫一眼解析,看看自己的思路和解析是否一致。如果解析用了更优的方法,记下来。如果解析的方法比你的更繁琐,那说明你的方法可能更好,也可以记下来。
解析里我特意加了一些“易错点”和“扩展知识”的标注。这些内容在考场上不一定直接考,但能帮你建立更完整的知识体系。比如在讲补码的时候,我顺带提了一下原码和反码的区别,虽然初赛不直接考反码,但理解了反码能帮你更好地理解补码。
最后再分享一个小技巧:把这份卷子里所有你做错的题,对应的知识点写在一张纸上,贴在书桌前。每天看一遍,连续看一周。一周之后,这些知识点基本就刻在脑子里了。这个方法我用过很多次,对考前突击特别有效。
这份卷子的解析部分,我尽量写得详细,每一步都标了理由。但如果你发现某道题的解析看不懂,或者觉得有更好的解法,欢迎随时来交流。初赛的题目有时候确实会有多种理解方式,多讨论才能把问题吃透。