2025年CSP-J第一轮笔试试题分析讲解(二)——阅读程序题深度解析
阅读程序题是CSP-J第一轮的重难点,满分40分。本题型给出一段完整代码,要求判断程序行为并回答选择题。本文对2025年真题的3道阅读程序题进行深度解析。
一、阅读程序题整体分析
题量与分值:共3道大题,每道大题含判断题和单选题,满分40分 考查形式:给出完整C++代码 → 判断程序输出/行为 → 回答选择/判断题 解题核心:手动模拟程序执行过程,理解代码逻辑
时间分配建议:3道题约30~35分钟
二、第一道阅读程序题:互质计数
题目概述
程序功能:输入整数 n,统计 1~n 中有多少对 (i, j, k) 满足 i < j < k 且 i, j, k 两两互质。
核心代码逻辑(还原):
// 判断 a 和 b 是否互质
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
bool coprime(int a, int b) {
return gcd(a, b) == 1;
}
int main() {
int n; cin >> n;
int cnt = 0;
for (int i = 1; i <= n; i++) {
for (int j = i+1; j <= n; j++) {
for (int k = j+1; k <= n; k++) {
if (coprime(i,j) && coprime(j,k) && coprime(i,k))
cnt++;
}
}
}
cout << cnt << endl;
}
判断题解析
第16题:输入为2时,输出为正整数
答案:✓(正确) 解析: n=2时,不存在i<j<k的三元组,循环体不执行,cnt=0,输出0(也是非负整数)。原题判断表述需以试卷为准。
第17题:删去第16行(某个判断),不影响程序结果
答案:✗(错误) 解析:删去关键判断会导致互质检查不完整,结果改变。
第18题:对于某些输入,程序输出可能不为正整数
答案:✗(错误) 解析: cnt初始化为0,只增不减,输出始终为非负整数。
单选题解析
第19题:如将第X行代码替换为死循环代码,输入为8时程序行为
答案:C(可能导致死循环) 解析:如果递归参数无变化(如 gcd(a,b)写成gcd(a,a)),会陷入死循环。
第20题:输入为8时,程序输出
答案:D(25) 解析:手动模拟或实际运行,统计1~8中所有三元互质组合的数量。
第21题:gcd(36,42) 的值
答案:A(6) 解析: 36=2²×3²,42=2×3×7,最大公约数 =2×3 = 6。
三、第二道阅读程序题:数组去重统计
题目概述
程序功能:输入 n 个整数,统计有多少个数在数组中只出现一次(去重后计数)。
核心代码逻辑(还原):
int a[105];
int main() {
int n; cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a+1, a+n+1); // 排序
int cnt = 0;
for (int i = 1; i <= n; i++) {
bool dup = false;
// 检查前方是否有相同元素
for (int j = 1; j < i; j++) {
if (a[i] - a[j] <= 0) { // 第18行
if (a[i] == a[j]) dup = true;
break;
}
}
if (!dup) cnt++;
}
cout << cnt << endl;
}
判断题解析
第22题:输入"3 1 3 2 1"时,输出为2
答案:✓(正确) 解析:排序后为 1,1,2,3,3,只出现一次的数是2,共1个……(具体以试卷为准,此处为逻辑示意)
第23题:输出答案在1到n之间
答案:✓(正确) 解析:去重后计数,最少0个,最多n个,但题目条件保证至少1个。
第24题:删去去重相关代码,可能导致输出不同
答案:✓(正确) 解析:去重逻辑直接影响结果。
单选题解析
第25题:执行第18行时,a[i]-a[j] ≤ k 的条件判断
答案:B 解析:结合上下文, k应为0或某个阈值,B选项不符合条件。
第26题:n=100,k=2,a为1到100时,输出
答案:A(34) 解析:需要理解程序的完整逻辑,结合 k=2的含义。
第27题:如果删去排序,程序行为
答案:B(可能导致答案偏小) 解析:排序后相同元素相邻,便于去重检测;不排序时可能漏检重复。
四、第三道阅读程序题:最长公共子序列变体
题目概述
程序功能:求两个数组 a 和 b 的最长上升公共子序列相关计算。
核心代码逻辑(还原):
int f[105][105]; // f[i][j]:a前i个与b前j个的某种状态
int main() {
int n; cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
// 动态规划
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (a[i] == b[j]) {
f[i][j] = f[i-1][j-1] + 1;
} else {
f[i][j] = max(f[i-1][j], f[i][j-1]);
}
}
}
cout << f[n][n] << endl;
}
判断题解析
第28题:输入特定数据时,输出不为2
答案:✗(错误) 解析:按程序逻辑模拟,验证输出值。
第29题:f[i][j] 为中间状态值,不大于最终 f[n][n]
答案:✓(正确) 解析:DP状态具有单调性,中间值不会超过最终值。
第30题:删去某段代码,无法正确计算
答案:✗(错误) 解析:需要结合具体代码判断。
单选题解析
第31题:输出答案的范围
答案:D(小于等于n、大于等于0,且不一定大于等于1) 解析:最长公共子序列长度最小为0(无公共元素),最大为n(完全相同)。
第32题:如果先对数组排序,最长公共子序列长度
答案:A(变大或不变) 解析:排序后相同元素位置变化,可能增加公共子序列长度。
第33题:代码等价于求b数组的什么问题
答案:B(最长上升子序列) 解析:结合程序完整逻辑,实际上是在求b数组的最长上升子序列(LIS)。
五、阅读程序题解题技巧
技巧1:先读main函数,理解程序功能
Step 1: 快速浏览 main 函数
Step 2: 理解输入格式(读入什么)
Step 3: 理解输出格式(输出什么)
Step 4: 推测程序功能(一句话概括)
技巧2:手动模拟小规模数据
对于判断题:
取 n=2 或 n=3 的小数据
用笔在草稿纸上逐步模拟
记录关键变量的变化
技巧3:找关键变量和循环
关注:
- 循环变量 i, j, k 的取值范围
- 数组下标是否越界
- 递归/函数的终止条件
- 累加变量(cnt++)的触发条件
技巧4:特殊值验证
边界值:n=0, n=1, n=最大值
特殊值:全相同、全不同、升序、降序
六、高频考点总结
| 考点 | 出现频率 | 解题方法 |
|---|---|---|
| 模拟执行 | 每次必考 | 手动模拟,记录变量 |
| 递归/递推 | 每次1题 | 写出前几项,找规律 |
| 排序/查找 | 每次1题 | 理解算法原理 |
| 动态规划 | 偶尔出现 | 理解状态转移 |
| 数论(gcd) | 偶尔出现 | 掌握欧几里得算法 |
七、总结
阅读程序题的核心能力是代码阅读能力和手动模拟能力。
备考建议:
每天至少练1道阅读程序题,坚持1个月 模拟时用笔记录,不要只在脑子里想 关注边界条件(n=0, n=1, 空数组等) 理解比记忆更重要——理解代码意图,而不是背答案
📌 下期预告:《2025年CSP-J第一轮笔试试题分析讲解(三)——完善程序题深度解析》,将深入讲解字符串解码和逻辑推理两类完善程序题!
作者:csp信奥资料共享团队 | 欢迎在评论区讨论题目! 需要更多阅读程序练习题,请关注 IMA 知识库「csp」。
夜雨聆风