1 条题解
-
0
2025年 CSP-J 第一轮试题解答
一、 单项选择题
1. [2 分] 一个 32 位无符号整数可以表示的最大值
答案:A
解析:32 位无符号整数的取值范围是 到 。
- 因此,最大值 最接近 。
2. [2 分] C++ 位运算
x & (x - 1)答案:B
解析:
x & (x - 1)是一个经典操作,用于将x的二进制表示中最右边的 1 变为 0。x = 255的二进制是11111111。x - 1 = 254的二进制是11111110。- 按位与的结果是
11111110,即十进制的 254。
3. [2 分] 递归函数
calc(5)答案:B
解析:我们自底向上计算:
calc(0) = calc(1) = 1calc(2) = calc(1) + 1 = 1 + 1 = 2(偶数)calc(3) = calc(2) + calc(1) = 2 + 1 = 3(奇数)calc(4) = calc(2) + 1 = 2 + 1 = 3(偶数)calc(5) = calc(4) + calc(3) = 3 + 3 = 6(奇数) 所以返回值是 6。
4. [2 分] 哈夫曼树带权路径长度 (WPL)
答案:B
解析:构造哈夫曼树的过程如下:
- 合并最小的两个:10 和 12 → 新节点 22。剩余:15, 20, 22, 25。
- 合并 15 和 20 → 新节点 35。剩余:22, 25, 35。
- 合并 22 和 25 → 新节点 47。剩余:35, 47。
- 合并 35 和 47 → 根节点 82。 计算 WPL:叶子节点深度乘以其权值再求和。
- 10 和 12 在第 3 层:
- 15 和 20 在第 2 层:
- 25 在第 2 层: 总 WPL = 。
5. [2 分] 有向图入度与出度之和
答案:B
解析:在有向图中,每条边都有一个起点(贡献一个出度)和一个终点(贡献一个入度)。因此,所有顶点的入度之和等于所有顶点的出度之和,且都等于图中的边数。
6. [2 分] 组合问题(男女生都有)
答案:C
解析:使用“正难则反”思想。
- 总选法:
- 全男生选法:
- 全女生选法:
- 满足条件的选法 =
7. [2 分] 逻辑表达式等价性
答案:C
解析:原表达式
(a && b) || (!c && a)可化简为a && (b || !c)(选项 A 正确)。- 选项 D:
!(!a || !b)等价于a && b,所以整个表达式为(a && b) || (a && !c),与原式相同。 - 选项 B:
(a || !c) && (b || !c) && (a || a)化简后也等价于a && (b || !c)。 - 选项 C:
a && (!b || c)。当a=true, b=false, c=false时,原式为false || true = true,而选项 C 为true && (true || false) = true?等等,重新验证:- 原式:
(T&&F) || (T&&T) = F || T = T - C:
T && (T || F) = T && T = T再试a=true, b=true, c=false: - 原式:
(T&&T) || (T&&T) = T || T = T - C:
T && (F || F) = T && F = F此时两者结果不同,故 C 不始终相等。
- 原式:
8. [2 分] 斐波那契模 7 数列
答案:D
解析:斐波那契数列模 7 存在周期(Pisano 周期)。我们列出数列直到出现循环
1, 1:1, 1, 2, 3, 5, 1, 6, 0, 6, 6, 5, 4, 2, 6, 1, 0, (1, 1)...周期长度为 16。- ,余数为 9。
- 数列第 9 项(从 开始计数)是 6。
9. [2 分] C++ string 类
答案:B
解析:
- A 错误:string 对象的长度可以通过
+=,append等方法改变。 - B 正确:C++ 允许
string + char或char + string。 - C 错误:
length()和size()是完全等价的成员函数,返回值总是相同。 - D 错误:虽然内部实现可能以
\0结尾,但这个结尾符不计入length()。
10. [2 分] C++ 引用与值传递
答案:C
解析:这是一个经典的交换函数,但有一个陷阱。
a是引用,b是值传递。- 执行
a = a + b;→x = 5 + 10 = 15 - 执行
b = a - b;→b = 15 - 10 = 5(这里的b是函数内的局部变量,不影响外部的y) - 执行
a = a - b;→x = 15 - 5 = 10最终,x变成了 10,而y因为是值传递,在函数内未被修改,仍为 10。所以结果是 10, 10。
11. [2 分] 网格路径问题
答案:B
解析:从 (1,1) 到 (4,5),需要向下走 步,向右走 步,共 7 步。 路径总数是从 7 步中选择 3 步向下(或 4 步向右)的组合数:$C_7^3 = \frac{7 \times 6 \times 5}{3 \times 2 \times 1} = 35$。
12. [2 分] 冒泡排序交换次数
答案:B
解析:模拟冒泡排序过程
{6,1,5,2,4}:- 第1轮:6与1换→
{1,6,5,2,4};6与5换→{1,5,6,2,4};6与2换→{1,5,2,6,4};6与4换→{1,5,2,4,6}(4次交换) - 第2轮:5与2换→
{1,2,5,4,6};5与4换→{1,2,4,5,6}(2次交换) - 第3轮及以后:无需交换。 总交换次数 = 4 + 2 = 6。
13. [2 分] 进制转换与加法
答案:A
解析:
- 保持不变。
- $270_8 = 2 \times 8^2 + 7 \times 8^1 + 0 \times 8^0 = 128 + 56 = 184_{10}$
- 和 =
- 将 904 转换为十六进制:,,。所以结果是 。
14. [2 分] 完全二叉树的叶子节点数
答案:C
解析:对于一棵有 个节点的完全二叉树,其叶子节点数为 。
- ,。 另一种思考:最后一个非叶子节点的编号是 ,所以叶子节点编号从 501 到 1000,共 500 个。
15. [2 分] 栈与队列的模拟
答案:A
解析:按规则模拟处理队列 A
[7,5,8,3,1,4,2]:- 7 (奇): S =
[7] - 5 (奇): S =
[7, 5] - 8 (偶, S非空): P =
[5], S =[7] - 3 (奇): S =
[7, 3] - 1 (奇): S =
[7, 3, 1] - 4 (偶, S非空): P =
[5, 1], S =[7, 3] - 2 (偶, S非空): P =
[5, 1, 3], S =[7]最终队列 P 的内容是 5,1,3。
二、 阅读程序
(1) 三元组互质计数
判断题
- A (正确)。输入 n=2,外层
i最大到 2,j从i+1=3开始,但3 > n=2,所以内层循环不会执行,自然不会执行第16行的判断。 - B (错误)。三个数两两互质是一个整体条件。删去
gcd(i,k)==1后,只要i,j和j,k互质就算,这可能导致i,k不互质的三元组被错误计入,结果会变大。 - B (错误)。题目提示此为错题。反例:当 n=6 时,无法找到三个两两互质的数(因为 2,3,4,5,6 中任意三个数总会包含一对不互质的数),输出为 0。
单选题
- B。将
gcd(b, a%b)改为gcd(a, a%b)会导致递归参数错误。例如gcd(36, 42)会变成gcd(36, 36%42=36)→gcd(36, 36)→gcd(36, 0)→ 返回 36。但实际上gcd(36,42)=6。这种错误会让gcd函数返回比实际值更大的数,导致更多三元组被认为不互质,最终输出的答案小于原答案。 - D。通过枚举或已知结论,当 n=8 时,满足条件的三元组数量为 25。
- A。
gcd(36, 42):42 % 36 = 6;36 % 6 = 0。所以返回 6。
(2) 动态规划去重数组
判断题
- A (正确)。输入为
n=3, k=1, a=[3,2,1]。排序去重后a=[1,2,3], n=3。
- i=1, j=0:
a[1]-a[1]=0 <= 1,ans[1]=ans[0]+1=1 - i=2, j=0:
a[2]-a[1]=1 <= 1,ans[2]=ans[0]+1=1 - i=3, j=0:
a[3]-a[1]=2 > 1, j++;a[3]-a[2]=1 <= 1,ans[3]=ans[1]+1=2输出ans[3]=2,正确。
- A (正确)。
ans[i] = ans[j] + 1,且ans[0]=0。ans数组单调不减,最小值为 1(当所有元素都在一个分组内),最大值为去重后的元素个数n。 - B (错误)。
std::unique的作用是去除相邻重复元素。如果输入数组本身没有重复元素,删除unique不会影响结果。题目问“有可能”,但标准答案认为在一般情况下(有重复时)才会影响,此处根据答案反推为 错误。
单选题
- B。第18行的
for循环结束后,j是满足a[i] - a[j+1] <= k的最大下标。因此a[i] - a[j+1] <= k,但a[i] - a[j]的关系不确定,不一定大于 k。 - A。
a={1..100}, k=2。算法本质是将数组划分为最少的组,使得每组内最大值与最小值之差不超过 k。最优分组为[1,2,3], [4,5,6], ..., [100],共 34 组 (前99个数33组,100单独一组)。 - B。
std::sort是算法正确性的前提。如果数组无序,a[i] - a[j+1] > k的判断将失去意义,可能导致本应分在同一组的元素被错误分开,从而使输出的答案比原本答案更小。
(3) 最长公共子序列 (LCS)
判断题
- A (正确)。输入为
n=4, a=[1,2,3,4], b=[1,3,2,2]。两个序列的 LCS 是[1,3]或[1,2],长度为 2。 - A (正确)。
f[i][j]表示a[1..i]和b[1..j]的 LCS 长度。随着i和j增大,LCS 长度只会增加或不变,不会减少。因此f[n][n]是全局最大值。 - B (错误)。第18行的代码
f[i][j] = max(f[i-1][j], f[i][j-1])是 LCS 状态转移的核心部分,用于处理a[i] != b[j]的情况。如果删除,f[i][j]将无法从历史状态继承正确的值,导致结果错误。
单选题
- D。LCS 的长度:
- 最小为 0(两个序列无公共元素)。
- 最大为
n(两个序列完全相同)。 - 不一定大于等于1(可能为0)。 所以 以上均是。
- A。对两个数组排序后,它们都变成了升序序列。此时,LCS 就变成了两个升序序列的最长公共子序列,这至少不会比原序列的 LCS 短(因为排序可能创造出新的、更长的公共子序列)。例如
a=[2,1], b=[1,2],原 LCS 长度为1;排序后a=[1,2], b=[1,2],LCS 长度为2。所以答案会变大或不变。 - B。当
a是严格递增序列[1,2,...,n]时,a和b的 LCS 就等价于在b中寻找一个最长的子序列,使其也是严格递增的。这正是 最长上升子序列 (LIS) 的定义。
三、 完善程序
(1) 字符串解码 (行程长度编码)
- C。要检查
z[i+1]是否为数字,必须确保i+1不越界,所以条件是i + 1 < z.length()。 - B。
count是一个多位数,需要从左到右逐位构建。标准的字符串转整数方法是count = count * 10 + (当前数字字符 - '0')。 - B。
count已经解析出完整的重复次数,循环count次即可。 - B。当前字符
ch只出现一次,直接将其加入结果字符串s。 - C。在
else分支中,我们已经处理了z[i],所以i需要自增以处理下一个字符。
(2) 精明与糊涂 (多数投票算法)
- B。初始候选人
candidate=0,其计数count应初始化为 1。 - C。当
count减到 0 时,说明当前候选人已被淘汰,需要选择一个新的候选人i。 - D。淘汰条件是:当前候选人
candidate认为i是糊涂人 或者i认为candidate是糊涂人。只要有一方说对方是糊涂人,就说明两人中至少有一个是糊涂人,可以进行抵消。 - A。发生抵消时,将当前候选人的计数
count减 1。 - C。经过消除过程后,最后剩下的
candidate就是精明人,直接输出 candidate。
- 1
信息
- ID
- 7893
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 94
- 已通过
- 6
- 上传者