乐于分享
好东西不私藏

2025年CSP-J第一轮笔试试题解析(二)—— 阅读程序题精讲

2025年CSP-J第一轮笔试试题解析(二)—— 阅读程序题精讲

2025年CSP-J第一轮笔试试题分析讲解(二)——阅读程序题深度解析

阅读程序题是CSP-J第一轮的重难点,满分40分。本题型给出一段完整代码,要求判断程序行为并回答选择题。本文对2025年真题的3道阅读程序题进行深度解析。


一、阅读程序题整体分析

题量与分值:共3道大题,每道大题含判断题和单选题,满分40分 考查形式:给出完整C++代码 → 判断程序输出/行为 → 回答选择/判断题 解题核心手动模拟程序执行过程,理解代码逻辑

时间分配建议:3道题约30~35分钟


二、第一道阅读程序题:互质计数

题目概述

程序功能:输入整数 n,统计 1~n 中有多少对 (i, j, k) 满足 i < j < ki, 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(可能导致答案偏小)
  • 解析:排序后相同元素相邻,便于去重检测;不排序时可能漏检重复。

四、第三道阅读程序题:最长公共子序列变体

题目概述

程序功能:求两个数组 ab最长上升公共子序列相关计算。

核心代码逻辑(还原):

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道阅读程序题,坚持1个月
  2. 模拟时用笔记录,不要只在脑子里想
  3. 关注边界条件(n=0, n=1, 空数组等)
  4. 理解比记忆更重要——理解代码意图,而不是背答案

📌 下期预告:《2025年CSP-J第一轮笔试试题分析讲解(三)——完善程序题深度解析》,将深入讲解字符串解码和逻辑推理两类完善程序题!


作者:csp信奥资料共享团队 | 欢迎在评论区讨论题目! 需要更多阅读程序练习题,请关注 IMA 知识库「csp」。