2025CSPJ初赛
h_h__h_h
·
2025-09-20 23:30:46
·
生活·游记
原题和主要内容来源,感谢!
修改了部分答案,主要是阅读题和最后摩尔投票部分,如有异议辛苦指出。全卷只有摩尔投票上课没讲过。做了琪露诺的有福了,j超纲考了滑动窗口。
【算法讲解116【扩展】摩尔投票大加强,线段树里捉海王-哔哩哔哩】 https://b23.tv/IL8dH0F
【【漫士】这是你学明白组合数学最好的机会-哔哩哔哩】 https://b23.tv/T74ik41
选择
题号
答案
解析要点
1
A
int最大约2E9,速算32位无符号整数unsinged int最大约4E9, 2³² - 1 ≈ 4×10⁹
2
B
255(二进制 11111111)与 254(11111110)按位与结果为 254
3
B
递归计算得 calc(5) = cal(4)+cal(3)=cal(2)+1 + cal(2)+cal(1) = cal(1)+1 +1 + cal(1)+1 + 1 = 6
4
B
哈夫曼树构造后,带权路径长度为:10×3 + 12×3 + 15×2 + 20×2 + 25×2 = 186 =10*3+12*3+15*2+20*2+25*2
5
B
有向图中每条边贡献1个入度和1个出度,故入度和 = 出度和 = 边数
6
C
正难则反,排除法排除全女全男 C(9,4) - C(5,4) - C(4,4) = 126 - 5 - 1 = 120
7
C
逻辑运算符按结合律化简为 a && (b
!c),选项C为 a && (!b
c),不相等
8
D
打表发现斐波那契数列模7周期为16(1, 1, 2, 3, 5, 1, 6, 0, 6, 6, 5, 4, 2, 6, 1, 0),2025 mod 16 = 9,对应值为6
9
B
string类支持+连接string与char;A(长度可改,甚至有resize函数)、C(length=size)、D(结尾符不计入)均错
10
C
引用传递a(x被修改为10),值传递b(y保持10)
11
B
⭐经典杨辉三角。需向右3步、向下4步,总路径数 C(7,3) = 35
12
B
冒泡排序共发生6次元素交换(第一轮4次,第二轮2次)6 1 5 2 4-> 1 5 2 4 6-> 1 2 4 5 6
13
A
十进制720 + 八进制270(十进制184)= 904,转十六进制为 0x388
14
C
数学归纳法可证(也可以想奇数时多一个叶子,偶数是正好叶子持平)n个节点的完全二叉树,叶子节点数为 n - n//2
15
A
模拟,队列P依次存入 5、1、3
T16 两两互质的三元组+辗转相除法求GCD
import math
def gcd(a, b):
return math.gcd(a, b)
n = 8
ans = 0
for i in range(1, n + 1):
for j in range(i + 1, n + 1):
for k in range(j + 1, n + 1):
if gcd(i, j) == 1 and gcd(j, k) == 1 and gcd(i, k) == 1:
ans += 1
print(i,j,k)
print(ans)
题号
答案
解析要点
16
√
输入 n=2 时,i\<j\<k 无合法组合,第16行判断不执行
17
×
删去 gcd(i,k)==1 会漏选 i 与 k 不互质的情况,结果偏大
18
√
n≥3 时,至少存在 (1,2,3) 等两两互质三元组,输出为正整数
19
B
举例试一下即可,gcd总是a不变b快速变零导致gcd结果很难是1,最后ans=0
20
D
枚举吧,试了下分类讨论也挺累的,老实模拟枚举
21
A
36 与 42 的最大公约数为 6
⭐T17把已排序、去重后的数组切成最少连续子段,使得每一段内部最大值减最小值 ≤ k,最终输出最少段数。(一般看到本题直接二分答案来着,学一下滑动窗口+DP)
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int n, k;
int a[200007];
int ans[200007];
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
/* 去重:unique 返回去重后尾端指针,减 a 得新长度 */
sort(a + 1, a + n + 1);
n = unique(a + 1, a + n + 1) - a - 1;
/* 滑动窗口核心逻辑 */
for (int i = 1, j = 0; i <= n; ++i) {
while (j < i && a[i] - a[j + 1] > k) ++j; // 把过期的左端点右移
ans[i] = ans[j] + 1; // 以 a[i] 结尾的最少段数
}
printf("%d\n", ans[n]);
return 0;
}
题号
题型
答案
解析要点
22
判断题
√
输入处理后排序去重,ans[3] = 2,输出正确
23
判断题
√
ans[n] 为子序列个数,范围 1 ≤ ans[n] ≤ n
24
判断题
×
重复元素差值为0,对结果没影响吧。而且本题代码对k<0的输出恒为1
25
单选题
B
退出循环时 a[i] - a[j+1] ≤ k,但 a[i] - a[j] 可能 ≤k(非必然 >k)
26
单选题
A
每3个元素为一组,100个元素对应34组,ans[100] = 34
27
单选题
A
未排序时数组无序,可能导致 ans[n] 偏大(如逆序数组,ai-aj+1<0,j指针几乎不移动,几乎没累加)
T18 LCS纯模板,典中典
题号
题型
答案
解析要点
28
判断题
√
a=[1,2,3,4]、b=[1,3,2,2] 的 LCS 长度为 2
29
判断题
√
f[i][j] 为局部 LCS 长度,必然 ≤ 全局最大值 f[n][n]
30
判断题
×
删去第18行后,无法继承 f[i-1][j] 或 f[i][j-1] 的最大值,结果错误
31
单选题
D
LCS 长度 ≤ n(A对)、≥ 0(B对)、可能为 0(C对)
32
单选题
A
排序后 LCS 变为公共元素个数,可能变大(如乱序数组)或不变
33
单选题
B
若 a 为有序数组,LCS 等价于 b 的最长上升子序列(LIS)⭐题号填涂有问题的同学可以之后考虑申诉成绩
完善程序T19字符串解码T20摩尔投票
#include <cctype>
#include <iostream>
#include <string>
using namespace std;
int main() {
string z;
cin >> z;
string s = "";
for (int i = 0; i < z.length(); ) { // ① 初始化 i = 0
char ch = z[i];
if (isalpha(ch) && i + 1 < z.length() && isdigit(z[i + 1])) {
i++; // 跳过字母
int count = 0; // ② 初始值 count = 0
while (i < z.length() && isdigit(z[i])) {
count = count * 10 + (z[i] - '0'); // ③ 数字拼接
i++;
}
for (int j = 0; j < count; j++) // ④ 重复 count 次
s += ch;
} else {
s += ch; // 普通字母
i++;
}
}
cout << s << endl;
return 0; // ⑤ return 0
}
题号
答案
解析要点
33
C
需判断下一个字符是否在字符串内(i+1 < z.length())
34
B
数字拼接逻辑:count = count * 10 + (z[i] - '0')
35
B
循环次数为解析出的重复次数 count
36
B
无后续数字时,直接添加当前字符 ch
37
C
处理完单个字符后,i 需自增1(i++)
38
B
初始候选者为 0,计数 count = 1
39
C
票数归零,更换候选者
40
D
意见不合,候选人票数-1
41
A
意见不合,候选人票数-1
42
C
最终留下的候选者为精明人,输出 candidate