
2025年CSP-J初赛第一轮刚结束那会儿不少孩子出了考场就跟我发消息有的说“选择题稳了”有的说“阅读程序第三题直接看懵了”。作为一个带过好几轮信息学竞赛的教练我每年都会盯着这套题看今年也不例外。CSP-J第一轮虽然是笔试但它的价值不只是“过线进复赛”更在于帮你检验算法思维和代码阅读能力到底扎不扎实。这篇文章我就把今年第一轮的题目和答案逐题拆开聊重点讲清楚每一道题背后的知识点、坑点以及下次遇到同类题该怎么下手。无论你是今年刚考完想对答案的选手还是准备明年参赛的初学者这篇文章都值得认真过一遍。1. 2025年CSP-J初赛整体情况与考查趋势1.1 今年题目难度与风格变化从整体看2025年CSP-J第一轮保持了往年的题型结构单项选择、阅读程序、完善程序三大板块满分100分考试时间120分钟。难度上和2024年相比略有提升尤其是阅读程序部分出现了两段需要结合递归和状态分析的代码往年这种深度的题目更多出现在提高组今年放到入门级明显是想强化对“代码执行过程”的考查。另外今年的单选题里进制转换、逻辑表达式、排列组合的题目数量基本没变但数据结构部分的题比去年多了一道涉及二叉树的遍历和堆的性质。这说明命题组在入门级越来越重视“把数据结构基础打牢”这个信号。从2025年的CSP-J考纲来看树和图的内容确实被反复强调所以今年这个变化并不意外。1.2 核心考点分布与分值占比我根据能回忆起来的题目做了一个考点分布统计方便大家直观感受。考点模块题量约分值占比典型考察形式计算机基础与常识硬件、操作系统、编码4-5题10分左右概念记忆、简单计算进制转换与位运算3题6分直接计算、逻辑判断数学基础排列组合、概率、整除4题8分排列组合公式、整除性质数据结构栈、队列、树、堆、图5题10分性质判断、遍历结果基础算法排序、二分、贪心、递归4题8分复杂度分析、正确性判断阅读程序3大题40分模拟执行、输出结果、功能判断完善程序2大题30分代码填空、逻辑补全这个分布和往年高度一致说明CSP-J初赛的核心还是考查“计算机通用能力 代码理解能力”而不是偏题怪题。备考时只要把每个模块的核心知识点吃透拿高分并不难。2. 单项选择题详细解析2.1 计算机基础与常识部分单项选择题的第一部分通常是送分题但每年都有孩子在这里丢分原因是知识点太碎复习时容易漏掉。今年出现了这道题题目回忆版现代计算机中CPU能直接识别和执行的语言是 。A. 汇编语言 B. 高级语言 C. 机器语言 D. 自然语言答案是C。这道题属于概念必考题机器语言是唯一能被CPU直接执行的二进制指令集合。很多同学会选A觉得汇编语言已经很“底层”了但汇编语言仍然需要经过汇编器翻译成机器码才能执行。这里有一个记忆技巧翻译成机器码的步骤越少语言就越接近底层机器语言不需要任何翻译是CPU的“母语”。今年还考了一道关于ASCII编码的题问字符0的ASCII码值是多少。答案是48。这道题背后的意义在于ASCII码表需要背下来几个关键点大写字母A是65小写字母a是97数字字符0到9是48到57。这样遇到“小写字母比大写字母大32”的运算题时就能快速反应。另外还考了常见存储单位的换算问1GB等于多少MB答案是1024。别觉得这种题太基础每年都有孩子在这里因为粗心丢分。2.2 进制转换与位运算进制转换是CSP-J选择题的常客今年考了一道二进制加法运算题题目回忆版二进制数10110与二进制数01101相加结果为 。A. 100011 B. 100010 C. 100001 D. 101011先把两个数转成十进制10110₂ 16 4 2 2201101₂ 8 4 1 1322 13 35 100011₂。答案是A。这种题最快的方法是按位相加但容易进位出错我建议考试时用“转十进制加完再转回二进制”的方式既不容易错速度也不慢。位运算部分考了一道“按位与”和“按位或”的混合题给了一个表达式(12 10) | 6。12的二进制是110010是1010按位与得到10008再和60110按位或得到111014。答案是14。这类题的关键是先把十进制转成二进制然后逐位运算最后再转回十进制。注意位运算题的运算优先级要记牢。按位取反(~)优先级最高然后依次是移位(, )、按位与()、按位异或(^)、按位或(|)。如果表达式中混了逻辑运算符要先算位运算再算逻辑运算否则很容易算错。2.3 数学基础与逻辑推理数学部分每年都会考排列组合今年也不例外。有一道题题目回忆版从5名男生和3名女生中选出3人要求至少包含1名女生共有多少种选法A. 46 B. 56 C. 40 D. 48这种带限制条件的组合题最稳的方法是用“总数减去不符合条件的情况”。总数是从8个人里选3个C(8,3) 56。不符合条件的是“3人全是男生”即C(5,3) 10。所以符合条件的选法是56 - 10 46。答案是A。如果直接用“选1女2男”或“选2女1男”或“选3女”分类算也能得到46但分类容易漏算尤其容易漏掉“3女”这种边界情况所以减法思路更稳妥。逻辑表达式部分考了一道“非、与、或”的混合判断题比如!p || q在p为true、q为false时的结果。这道题只要记住“非”的优先级最高然后“与”高于“或”就能快速判断。!true是falsefalse || false是false答案是false。逻辑题的关键是不要靠直觉老老实实把优先级列出来再算。2.4 数据结构与算法基础数据结构的题今年多了难度也稍微上来了一点。有一道栈的题题目回忆版元素入栈顺序为1, 2, 3, 4则出栈顺序不可能是 。A. 2, 1, 3, 4 B. 3, 2, 1, 4 C. 4, 3, 2, 1 D. 1, 4, 3, 2答案是D。为什么D选项要求1先出栈说明1入栈后立即出栈但随后4出栈意味着2、3、4都已经入栈可4出栈后栈里还压着2和3由于2在3下面所以下一项出栈的只能是3不可能是2。这个题考察的核心是“栈后进先出”的性质做题时最好在草稿纸上画一下栈的变化过程不要光在脑子里想。二叉树遍历也考了一道给出前序遍历和中序遍历求后序遍历。这类题的通用解法是前序第一个是根在中序中找到根的位置根左边是左子树右边是右子树然后递归处理。今年给的具体序列我记不太清了但解题思路是完全固定的先找根再切分左右子树最后按“左右根”的顺序输出后序序列。树的题目只要掌握了这个递归套路基本不可能丢分。3. 阅读程序题逐段拆解3.1 第一道阅读程序题递归与全局变量今年的第一道阅读程序题考了一个递归函数大致如下#include iostream using namespace std; int cnt 0; void func(int n) { if (n 1) return; cnt; func(n / 2); func(n - n / 2); } int main() { func(10); cout cnt endl; return 0; }题目问输出是多少。我拿到这种题第一反应不是直接递归地去执行而是画一棵递归树。func(10)会调用func(5)和func(5)这两个func(5)又会各自调用func(2)和func(3)接着继续往下分裂。每次进入n 1的分支cnt就加1。最后算出来cnt是9。这道题的坑在于很多孩子看到func(n / 2)和func(n - n / 2)觉得“这两个参数加起来等于n应该不会重复计算”实际上递归树从第二层开始就会出现重复子问题比如func(5)被调用两次每棵子树都会独立地执行自己的递归计数。如果计算的时候漏掉了其中一个分支结果就会差出2到3个计数。3.2 第二道阅读程序题位运算与循环计数第二道题是一段经典的循环和位运算结合的代码#include iostream using namespace std; int main() { int n; cin n; int ans 0; while (n) { ans; n (n - 1); } cout ans endl; return 0; }这道题问的是输入n为1023时输出是多少。n (n - 1)的作用是每次把n的二进制表示中最右边的那个1变成0。循环每执行一次就消掉一个1循环次数就是二进制中1的个数。1023的二进制是1111111111也就是10个1所以答案是10。这其实是“统计二进制中1的个数”的最经典写法。我把这道题拿出来讲是因为它代表了一类高频考点位运算的“奇技淫巧”。除了n (n-1)还要记住n (-n)能取到最低位的1(n k) 1能取出第k位的值。这些技巧在阅读程序题里反复出现做题时一旦识别出“这是位运算经典写法”就能立刻明白程序的功能而不需要逐行模拟。3.3 第三道阅读程序题结构体排序与比较函数第三道阅读题给了一个结构体排序的完整代码核心是比较函数struct Node { int x, y; }; bool cmp(Node a, Node b) { if (a.x ! b.x) return a.x b.x; return a.y b.y; }这个比较函数的含义是先按x从小到大排序当x相同时按y从大到小排序。题目给了几个结构体数组问排序后第一个元素是什么。这类题只要把握一点比较函数返回true表示“a应该排在b前面”。所以a.x b.x就是x升序a.y b.y就是y降序。这道题虽然简单但每年都有同学在“升序还是降序”上犯迷糊。我教学生的时候喜欢这样记比较函数就是在回答“a要不要站到b前面”条件是a.x b.x那就是小的在前升序。如果条件写的是a.x b.x那就是大的在前降序。这个理解方式适用于所有排序相关的题包括后续复赛里手写sort的cmp函数也是同一个道理。4. 完善程序题解题思路与代码填空技巧4.1 完善程序一二分查找的边界处理今年的第一道完善程序题考了二分查找题目给出了一个升序数组要求查找目标值target找到则输出下标找不到则输出-1。核心代码如下int binarySearch(int arr[], int n, int target) { int left 0, right n - 1; while (left right) { int mid (left right) / 2; if (arr[mid] target) return mid; if (arr[mid] target) { left mid 1; // 填空1 } else { right mid - 1; // 填空2 } } return -1; }这两个空是二分查找的基础操作但很多初学者会写成left mid或者right mid导致死循环。关键在于当arr[mid] target时target一定在mid的右边而arr[mid]已经确定了不等于target所以新的搜索区间应该从mid 1开始而不是从mid开始。同理当arr[mid] target时搜索区间的右边界要缩到mid - 1。提醒二分查找的边界是完善程序题里最常见的考点背住一个模板还不够还要理解为什么是mid1和mid-1。这样才能应对各种变体比如找左边界、找右边界、在旋转数组里查找等。4.2 完善程序二动态规划求最长上升子序列今年第二道完善程序题是求最长上升子序列LIS的动态规划题给出了 O(n²) 的解法框架int LIS(int arr[], int n) { int dp[1005]; int ans 0; for (int i 0; i n; i) { dp[i] 1; for (int j 0; j i; j) { if (arr[j] arr[i]) { dp[i] max(dp[i], dp[j] 1); // 填空 } } ans max(ans, dp[i]); } return ans; }这里的核心逻辑是dp[i]表示以第i个元素结尾的最长上升子序列长度。初始化时每个元素自己单独就是一个长度为1的子序列所以dp[i] 1。内层循环遍历i之前的所有元素j如果arr[j] arr[i]说明arr[i]可以接在arr[j]后面形成一个更长的上升子序列长度是dp[j] 1用max函数更新dp[i]。这道题虽然考的是动态规划但填空本身并不难。真正的难点在于很多选手不理解dp数组的含义导致在max(dp[i], dp[j] 1)这个填空中犹豫不决甚至写成dp[i] dp[j] 1。这样写的问题在于如果没有多个j可以接续dp[i]会被最后一个符合条件的j覆盖而不是取最大值最终结果就错了。4.3 完善程序答题策略从答案反推逻辑做完善程序题有一个非常实用的策略先不要急着看空先通读整段代码搞清楚变量名和数据结构的含义。比如看到dp就想到动态规划看到left, right, mid就想到二分查找看到head, next就想到链表或邻接表。接着再逐段读代码把每个变量的作用写在草稿纸上最后再去看空这时候你会发现很多空其实就是“翻译”已经读懂的逻辑。另外一个技巧是“代入样例验证”。如果题目给了输入输出样例填空之后把样例代进去用纸笔模拟一遍代码执行如果输出和题目给的一致说明大概率没问题。这个技巧在考试时特别管用因为有些空你不太确定填A还是B代入样例一跑基本就能排除错误选项。5. 常见失分点与避坑指南5.1 时间分配不合理每年都有孩子在做选择题时过于纠结一套选择题花掉60分钟结果阅读程序和完善程序连题都看不完。我的建议是选择题每题最多2分钟超过2分钟就凭第一印象选一个并做上标记等全部写完再回头想。阅读程序和完善程序的分值高、单题耗时也长至少要留60到70分钟。这里有一个很现实的道理初赛的及格分是60分部分地区是50分根据实际规定只要你选择题能拿35分以上阅读程序和完善程序再拿一半分数进复赛基本就稳了。所以不要在个别难题上死磕。5.2 阅读程序不画执行过程阅读程序题最忌讳“光盯着代码看脑子里模拟”。人脑的缓存是有限的一段十几行的递归代码靠脑补很容易漏掉一层。我在带学生的时候反复强调拿到阅读程序题第一件事就是拿草稿纸把变量写出来一行一行地更新。尤其是循环里的变量变化、递归的调用栈画出来比想出来可靠得多。画执行过程看起来慢实际是快的。因为一旦画对了表后面所有的小题都能直接从表里找答案不需要重复读代码。比如今年那道递归计数题如果你把递归树画出来10秒钟就能数清楚调用了几次func(n 1)的分支但如果靠脑子一层一层想很容易在第三层开始混乱。5.3 数据结构题凭感觉判断数据结构的题不能凭“感觉”尤其是树、图、堆这些抽象结构一定要在草稿纸上画出来。我见过太多孩子在选择题里遇到“入栈顺序为1,2,3出栈顺序不可能的是”这种题直接脑子过一遍就选了结果漏掉了中间某个状态。正确的做法是把栈画成一个竖着的容器每push一个元素就往里放一个每pop一个就取最上面的那个把整个过程依次写出来。这个习惯在初赛阶段就要养成因为到了复赛写代码时这些数据结构的基本操作也要靠脑子里的“画图”来帮助debug。5.4 忽视位运算和逻辑运算符的优先级优先级是选择题和阅读程序题的重灾区。很多孩子并不是不会位运算而是被混合表达式绕晕。我建议把常见运算符优先级按从高到低背下来括号、取反/自增自减、算术运算、移位、关系运算、按位与、按位异或、按位或、逻辑与、逻辑或、赋值。这样不管遇到多复杂的表达式先套优先级提纲再逐步计算基本不会出错。6. 2026年备考建议与冲刺计划6.1 按模块打基础从考纲出发如果你准备参加2026年的CSP-J现在就可以开始准备了。首先要做的不是刷题而是对照CSP-J考纲把计算机基础、进制转换、数学基础、数据结构、基础算法这五个模块过一遍。每一个模块至少要能回答三个问题这个知识点是什么它能解决什么问题它的典型例题怎么做我的经验是计算机基础部分不需要花太多时间考前一个月集中背即可真正决定初赛成绩的是“阅读程序”和“完善程序”这两块因为它们占的分值高需要长期训练代码理解能力。建议每周固定做3到5道阅读程序题不限时但要求把每一道题的执行过程完整写下来。6.2 真题是最好的训练材料初赛备考最有效的训练材料就是往年真题。从2019年到2024年的CSP-J第一轮真题每一道题都要吃透。吃透的意思是不仅知道正确答案还能解释错误选项为什么错。尤其是选择题很多干扰项设计得非常巧妙分析干扰项的过程本身就是一种训练。我建议整理一个错题本但不是把题目抄一遍而是记录“这道题的考点是什么”“我为什么会错”“下次怎么避免”。比如因为优先级没搞清而错的题就专门记一页“运算符优先级表”因为递归执行过程没画清而错的题就记一页“递归树画法示例”。这样的错题本考前翻一遍比盲目刷十套新题还有用。6.3 阅读程序能力是复赛的隐形门槛很多人觉得初赛就是背书加算题过了初赛再练编程不迟。这个想法很危险。初赛的阅读程序题本质上就是在考查“读代码”的能力而这种能力恰恰是复赛写代码、调bug的基础。一个读不懂别人代码的选手大概率也很难发现自己代码里的逻辑错误。所以我的建议是备考初赛的过程中每做一道阅读程序题都试着在编译器里把代码敲一遍运行一下观察结果和你的模拟是否一致。如果不一致就说明你对语言特性的理解还有偏差这种偏差就是初赛失分的根源也是复赛暴雷的隐患。初赛和复赛不是两场分离的考试而是一条能力进阶路径上的两个检查站。6.4 考场策略先易后难、及时止损最后聊一下考场上的临场策略。初赛的题目顺序是从易到难但因为每个人知识盲区不同你会遇到“前面选择题卡住后面阅读程序反而觉得简单”的情况。这时候千万不要恋战果断跳过不会的选择题先去做拿手的阅读程序和填空把能拿的分拿稳再回头啃硬骨头。CSP-J初赛看的是总分不是单题正确率学会止损也是一种能力。结语每年带学生考完CSP-J初赛我都会反复说初赛是检验不是审判。哪怕今年有几道题没做对也不代表你的编程能力不行更不代表你不适合走信息学这条路。真正重要的是通过这场笔试看清自己在计算机基础、算法思维、代码阅读上的短板在哪里然后利用接下来几个月的时间把短板一块一块补齐。我见过很多初赛低分飘过的孩子在复赛里反而写出了漂亮的程序因为他们在备考初赛时养成了严谨的模拟习惯和扎实的基础功底。希望这篇解析不仅能帮你对完答案更能帮你找到下一步努力的方向。如果这篇文章里的某道题、某个解析让你有恍然大悟的感觉那说明你已经吃透了那个考点如果你看完还有疑问别急着划走把题目抄下来自己动手敲一遍代码答案自然就浮出水面了。信息学这条路没有捷径但每一步都算数。