这份卷子是 《信息学奥赛CSP通关之路------CSP-J/S第一轮原创全真模拟试卷集(2026)》 这本书中的一套模拟题,接下来我将非常非常非常详细的为你们讲解这张初赛卷的每一道题。
单选题

1. 答案 B
考点 :Linux 基本命令
常识 :ls -l(长格式列表)可显示文件权限、硬链接数、所有者、大小、修改时间等完整属性。
-a仅用于显示隐藏文件(.和..),不包含详细属性;-s仅显示分配块数。

2. 答案 C
考点 :IP 地址分类
常识:
- A类:1.0.0.0 ~ 126.255.255.255
- B类:128.0.0.0 ~ 191.255.255.255
- C类:192.0.0.0 ~ 223.255.255.255
192.168.1.1首段为 192,明确属于 C 类地址。

3. 答案 B
考点 :C++ 逻辑运算与短路求值
计算过程 :
原式 = !(5>3) && (4<=4) || (2!=2)
5>3为true,取反得false4<=4为truefalse && true得false2!=2为falsefalse || false最终得false

4. 答案 D
考点:单向链表特性
- A 错:链表结点离散存储,只能顺序遍历,不支持随机访问(数组才支持)。
- B 错:插入/删除本身修改指针为 O(1),但若未知插入位置的前驱,则需 O(n) 查找,不能笼统称"都是 O(1)"。
- C 错:链表不要求连续存储空间。
- D 对:单向链表每个结点由数据域和指向后继结点的指针域组成。

5. 答案 B
考点 :二叉树最小高度
判断逻辑:
- A 错:(\lfloor \log_2 n \rfloor) 常用于计算完全二叉树高度,但未加 1 调整,n=2 时结果 1 虽对,但 n=3 时结果仍为 1(实际最小高度为 2),故不通用。
- B 对:满/完全二叉树形态下,高度为 (\lceil \log_2(n+1)\rceil - 1)(设根高度为 0)。
- C 错:(n-1) 是单支树(链表)的最大高度。
- D 错:高度为 1 最多只能容纳 2 个结点。

6. 答案 C
考点 :十进制小数转二进制
计算过程:
- 整数部分 :100 ÷ 2 = 50 余 0,50 ÷ 2 = 25 余 0,25 ÷ 2 = 12 余 1,12 ÷ 2 = 6 余 0,6 ÷ 2 = 3 余 0,3 ÷ 2 = 1 余 1,1 ÷ 2 = 0 余 1 → 逆序得
1100100 - 小数部分 :0.25 × 2 = 0.5(取整 0),0.5 × 2 = 1.0(取整 1)→ 得
.01
合并为1100100.01。

7. 答案 C
考点:排序算法的稳定性
- A 快排/ B 堆排 / D 选择排序:均为不稳定排序,交换或移动元素时可能改变相等元素的原始相对次序。
- C 归并排序 :合并时通过
<=控制顺序,保证相等元素相对位置不变,是稳定的,最适合"同分保序"场景。

8. 答案 C
考点 :存储设备易失性
常识:内存、缓存、寄存器均属半导体 RAM,断电即失;固态硬盘(SSD)基于闪存,属非易失性存储。

9. 答案 C
考点 :DFS 栈空间需求(路径最长结点数)
计算过程 :从左上角 (1,1) 到右下角 (n,m),每次仅向右或向下。
路径由 (n-1) 次向下和 (m-1) 次向右组成,路径上结点总数为:
(n−1)+(m−1)+1=n+m−1 (n-1) + (m-1) + 1 = n + m - 1 (n−1)+(m−1)+1=n+m−1
栈需记录整条路径的结点,故至少为 (n+m−1)(n+m-1)(n+m−1)。

10. 答案 C
考点 :循环时间复杂度分析
计算过程 :变量 i 从 1 开始,每次乘 3,循环执行至 i >= n。
设执行次数为 ttt,则 3t≥n3^t \ge n3t≥n,解得 t≈log3nt \approx \log_3 nt≈log3n,故复杂度为 O(logn)O(\log n)O(logn)。

11. 答案 A
考点 :完全图边数公式
计算过程 :8 个顶点的完全图,每对顶点间有一条边,边数:
C82=8×72=28 C_8^2 = \frac{8 \times 7}{2} = 28 C82=28×7=28

12. 答案 B
考点 :组合计数(分类加法)
计算过程 :
枚举并求和:
C51C31+C51C32+C51C33+C52C31+C52C32+C53C31=15+15+5+30+30+30=125 \begin{aligned} & C_5^1C_3^1 + C_5^1C_3^2 + C_5^1C_3^3 \\ +& C_5^2C_3^1 + C_5^2C_3^2 \\ +& C_5^3C_3^1 \\ = & 15 + 15 + 5 + 30 + 30 + 30 = 125 \end{aligned} ++=C51C31+C51C32+C51C33C52C31+C52C32C53C3115+15+5+30+30+30=125

13. 答案 B
考点:二叉搜索树(BST)遍历性质
- A 前序:根-左-右,不保证升序。
- B 中序:左-根-右,BST 中序遍历恰好输出升序序列。
- C 后序:左-右-根,无升序特性。
- D 层次:按层输出,同样不保证升序。

14. 答案 C
考点 :时间复杂度规模估算
计算过程 :T(n)∝n3T(n) \propto n^3T(n)∝n3,当 nnn 从 100 增至 200(变为 2 倍)时:
T(200)T(100)≈(200100)3=8 \frac{T(200)}{T(100)} \approx \left(\frac{200}{100}\right)^3 = 8 T(100)T(200)≈(100200)3=8

15. 答案 B
考点 :多媒体文件大小计算(单位换算)
计算过程:
- 总帧数 =10×60×30=1800010 \times 60 \times 30 = 1800010×60×30=18000 帧
- 每帧像素 =1920×1080=2,073,6001920 \times 1080 = 2,073,6001920×1080=2,073,600
- 24 位色 = 3 字节/像素 → 每帧字节 = 2,073,600×3=6,220,800B2,073,600 \times 3 = 6,220,800 B2,073,600×3=6,220,800B
- 未压缩总大小 = 18000×6,220,800=111,974,400,000B18000 \times 6,220,800 = 111,974,400,000 B18000×6,220,800=111,974,400,000B
- 除以压缩比 50 → 2,239,488,000B2,239,488,000 B2,239,488,000B
- 转换为 GB(按 102431024^310243):
2,239,488,000÷10243≈2.086 GB 2,239,488,000 \div 1024^3 \approx 2.086 \text{ GB} 2,239,488,000÷10243≈2.086 GB
约 2.1 GB。
阅读程序题
第一题
程序如下:

判断题:

16. 答案:√
解析 :函数 solve 采用更相减损术递归:当 y==0 返回 x;否则交换确保大数减小数,递归调用 solve(y, x-y)。该算法正确计算最大公约数。
17. 答案:×
解析 :若去掉第5行 if(x<y) swap(x,y);,当输入 x<y 时,递归调用 solve(y, x-y) 中的 x-y 为负数,后续无法满足 y==0 终止条件,会导致死循环或栈溢出,程序不能正常结束,并非"正常输出但结果不对"。
18. 答案:×
解析 :输入 160, 115,求最大公约数:
160-115=45,115-45=70,70-45=25,45-25=20,25-20=5,20-5=15,15-5=10,10-5=5,5-5=0,得 gcd=5。
输出应为 160/5=32,115/5=23,即 32/23。题干写 23/32,分子分母颠倒,错误。
选择题:

19. 答案:D(79/13)
解析 :输入 1817, 299,用辗转相除法:
1817=299×6+231817 = 299 \times 6 + 231817=299×6+23
299=23×13+0299 = 23 \times 13 + 0299=23×13+0
得 gcd=23。
输出分数:1817/23=79,299/23=131817/23=79,\quad 299/23=131817/23=79,299/23=13 故为 79/13。
A 错在未约分;B 错为错误计算;C 错在分母误写为最大公约数;D 正确。
20. 答案:B((O(\log n)))
解析 :更相减损术最坏情况为 (O(n)),但题目限定输入为 1~10000 随机数,平均迭代次数与对数成正比,故平均时间复杂度为 (O(\log n))。A 过小,C/D 过高。
第二题
程序如下:

判断题:

21. 答案:√
解析 :输入 [5,3,8,2]:
5:大于它的只有 8(cnt=1)→ 累加 5;
3:大于它的有 5,8(cnt=2)→ 不累加;
8:大于它的无(cnt=0)→ 不累加;
2:大于它的有 5,3,8(cnt=3)→ 不累加。
输出为 5,正确。
22. 答案:√
解析 :程序会累加所有满足"恰好一个元素大于它"的元素。例如 [5,5,8] 中两个 5 都满足(都只有 8 大于它们),均被累加,故存在多个元素满足条件时会被全部累加。
23. 答案:×
解析 :输出为 0 不一定所有元素相等。反例 [1,2,4,4]:
1:大于它的有 2,4,4(cnt=3);
2:大于它的有 4,4(cnt=2);
4:大于它的有 0(cnt=0)。
没有任何元素 cnt=1,输出为 0,但元素不全相等。
选择题:

24. 答案:C(8)
解析 :数组 [9,8,7,6,5,4,3,2,1,0,-1,-2] 为严格降序。
9:cnt=0;
8:大于它的只有 9(cnt=1)→ 累加 8;
其余元素:大于它们的至少 2 个,不累加。
输出为 8。
25. 答案:C
解析:程序统计所有满足"恰好有一个元素比它大"的元素之和。若第二大值有重复,则累加所有重复值。A 错在"第二大元素的值"通常指单个值;B、D 与平均值、最值无关。
第三题
程序如下:


判断题:

26. 答案:×
解析 :程序按位置枚举组合,相同数值但不同位置视为不同方案。例:nums=[1,1,2],k=2,选择两个 1(位置0,1)和为偶数计 1 次;若去掉一个 1,方案数改变,因此重复数字数量会影响结果。
27. 答案:×
解析 :去掉 nums.resize(n) 和 used.resize(n,false) 后,nums 和 used 大小均为 0,后续输入和访问 used[pos] 会下标越界,程序崩溃,不能正常运行。
28. 答案:×
解析 :1~10 中奇数 5 个,偶数 5 个。选 2 个数和为偶数需同奇或同偶:
C52+C52=10+10=20=2C52C_5^2 + C_5^2 = 10 + 10 = 20 = 2C_5^2C52+C52=10+10=20=2C52
题干写 (2C_6^2=30),与实际不符,故错误。
选择题:

29. 答案:B(1)
解析 :k=0 时,dfs(0,0,0) 立即判断 count==k 成立,sum=0 为偶数,ans++ 后返回,输出 1。空集和为偶数,算一种方案。A 错在误以为无方案;C 错在认为依赖数组值(实则不依赖);D 错。
30. 答案:C((O(2^n)))
解析 :DFS 对每个位置做选/不选分支,虽用 count==k 剪枝,但最坏情况(如 k≈n/2)仍需遍历指数级组合,时间复杂度上界为 (O(2^n))。A/B/D 均不符合递归枚举特征。
程序填空
(1)归并排序程序
原题:



程序作用 :这是标准的归并排序实现。程序先将数组一分为二(mSort 函数),递归排序左右两半,然后通过 merge 函数将两个有序子数组合并成一个完整有序数组。变量 L 和 R 分别暂存左半部分和右半部分的元素。
31. 答案:D(m + 1 + j)
解析 :这一步是在将原数组 a 的右半部分元素复制到临时数组 R 中。右半部分的起始下标是 m + 1,随着 j 从 0 递增,应依次取 a[m+1]、a[m+2]......因此表达式为 m + 1 + j。A 只取了 a[0];B 多加了 1 但未加 m;C 从 m 开始,包含了左半部分的最后一个元素,均错误。
32. 答案:C(i < n1 && j < n2)
解析 :这一步是合并两个有序数组 L 和 R 的循环条件。只要左半部分 L 还有剩余(i < n1)且 右半部分 R 还有剩余(j < n2),就需要不断比较并取较小者放入 a。一旦某一部分取完,循环结束,然后由后面的 while 语句处理剩余元素。A/B 中 n 是原数组总长度,不是子数组长度;D 使用 <= 会导致数组越界访问。
33. 答案:C(left, mid, right)
解析 :这一步是在 mSort 函数中对左右两半排序完成后,调用 merge 函数将二者合并。merge 函数的形参顺序是 (int l, int m, int r),因此实参必须按照 左边界、中间位置、右边界 的顺序传入,即 merge(left, mid, right)。A/B/D 的顺序均不符合函数定义。
34. 答案:A(0, n - 1)
解析 :这一步是在 main 函数中调用 mSort 对整个数组进行排序。因为数组 a 的下标范围是 0 到 n-1,所以左边界传 0,右边界传 n-1。B 的右边界 n 越界;C 和 D 从 1 开始会漏掉下标为 0 的元素。
35. 答案:B(a[n - 1])
解析 :这一步是输出排序后的数组。前面的 for 循环已经输出了从 a[0] 到 a[n-2],并且每个后面跟了空格("U" 是空格或分隔符的 OCR 识别)。最后一个元素不应再跟多余空格,应单独输出 a[n-1]。A 会在最后一个元素前多输出一个空格,破坏了输出格式的规范性;C 和 D 访问了 a[n],属于越界访问
(2)最长波动子序列程序
原题:


程序作用 :这是使用动态规划求解最长波动子序列的长度。dp[i][0] 表示以 nums[i] 结尾,且最后一段是上升 (即从上一个元素到 nums[i] 是上升趋势)的最长子序列长度;dp[i][1] 表示以 nums[i] 结尾,且最后一段是下降的最长子序列长度。程序遍历每个元素,并在其前面所有元素中寻找能形成波动的转移。
36. 答案:D(fill(dp[0], dp[0] + n * 2, 1);)
解析 :这一步是对 DP 数组进行初始化。对于序列中的每一个单独元素,它自身就可以构成长度为 1 的波动子序列(无论处于上升还是下降状态),因此需要将所有 dp[i][0] 和 dp[i][1] 都初始化为 1。dp 是一个二维数组,但在内存中连续排列,dp[0] 指向首元素,dp[0] + n * 2 正好指向数组末尾。A 的 memset(dp,1,sizeof(dp)); 按字节填充,1 会变成 0x01010101(十进制 16843009),不是预期的数值 1;B 赋的是极大值;C 中 dp ^ n*2 语法错误(异或),且 fill 的第一个参数也写错了。
37. 答案:C(j < i)
解析 :这一步是内层循环的遍历范围。题目要求找前面的 元素来构成子序列,i 是当前考察元素的下标,j 用于遍历 i 之前的所有元素,所以循环条件是 j < i。A/B 包含了自身及后面的元素,会导致重复计算或状态未定义;D 使用 <= 会将自身也算进去,转移逻辑错误。
38. 答案:A(nums[i] > nums[j])
解析 :这一步是判断当前元素 nums[i] 与前面的 nums[j] 是否构成上升 趋势。只有当 nums[i] > nums[j] 时,才能考虑从状态 dp[j][1](前面以 nums[j] 结尾且最后一段是下降)转移过来,形成上升趋势,从而更新 dp[i][0]。B 的 >= 忽略严格升降的波动要求(相等不算波动);C/D 将大小关系颠倒了,不符合上升的判断条件。
39. 答案:C(dp[j][0] + 1)
解析 :这一步是在 nums[i] < nums[j](构成下降 趋势)时,计算新的临时长度。既然要形成下降,前一个状态必须是以 nums[j] 结尾且最后一段是上升 的状态,即 dp[j][0]。在其基础上加上当前元素 nums[i],长度加 1,因此应填 dp[j][0] + 1。A 和 B 错误地使用了当前 i 的状态(还未计算完毕);D 使用了下降状态,无法形成下降趋势的连续转移。
40. 答案:C(max(dp[i][0], dp[i][1]))
解析 :这一步是更新最终答案 max_Len,它需要记录整个数组中所有位置、两种状态下能达到的最大长度。对于每个 i,以 nums[i] 结尾的波动子序列长度,无论是处于上升还是下降状态,都应参与比较,因此取二者中的较大值 max(dp[i][0], dp[i][1])。A 或 B 只取单个状态,会遗漏另一种可能性;D 取最小值完全错误。
以上是这张卷子的完整解析,祝各位复习愉快!:P