试卷解析 · 理解每一步
提高组 CSP-S 2026 初赛模拟卷 4
CSPS-2026-R1-Mock-4
试卷解析总览,可直接查看每题答案与解析。
第 1 题(单选题,2 分)
假设有以下定义:int a[5]={1,2,3,4,5}, i=3, *p=a, *q=a; 则不能正确执行的语句是( )。
正确答案B
解析详情
a 是数组,不能这样直接赋值,而 i, *p, *q 都是 int。
第 2 题(单选题,2 分)
下列不属于 CPU 的是( )。
正确答案C
解析详情
影驰 RTX2070 是显卡。
第 3 题(单选题,2 分)
(2019) + (2020) 的结果是()。
正确答案B
解析详情
都转成十进制: ,2019 + 1040 = 3059,BF3 十六进制转十进制: 。
第 4 题(单选题,2 分)
某二叉树的先序遍历序列和后序遍历序列正好相反,当且仅当该二叉树( )。
正确答案A
解析详情
选项 B、C、D 都只是充分条件,只有选项 A 是充要条件(实际上就是一条链,但左右都可以)。
第 5 题(单选题,2 分)
若有定义 char x[] = "12345"; char y[] = {'1', '2', '3', '4', '5}; 则()。
正确答案B
解析详情
字符串后有一个结束标记'\0'也占一字节,故x是6字节,y是5字节。
第 6 题(单选题,2 分)
公共汽车起点站于每小时的10分、30分、55分发车,某乘客不知发车时间,在每小时内的任一时刻随机到达车站,如果乘客到车站的时刻恰为发车时间就不能坐上此时发车的公共汽车,则乘客候车时间的数学期望(准确到秒)是()。
正确答案D
解析详情
每小时节点 55min~10min 的平均等候时间为 ,10min~30min 的平均等候时间为 ,30min~55min 的平均等候时间为 。则乘客等候时间的数学期望是 ,即为 10 分 25 秒。拿 55 分到 10 分的那一段简单说明一下:这一段一共 15 分钟,在一个小时中所占的时间比重为 15/60,而这一段的平均时间显然就是中间值为 15/2,所以这一块的期望贡献为 。
第 7 题(单选题,2 分)
设要将序列 Q, H, C, Y, P, A, M, S, R, D, F, X 中的关键码按字母的升序重新排列,则()是以第一个元素为分界元素的快速排序一趟扫描的结果。
正确答案A
解析详情
该题可以直接针对选项去除。第一个元素是 Q,看选项中 Q 之前的元素是否均小于 Q,之后的元素是否都大于 Q。如果仅有一个选项满足,则可以选择;如果有多个满足的选项,那么再按快速排序的方法,看看其他元素位置是否正确。
第 8 题(单选题,2 分)
设 G 是有 n 个节点、m 条边 (n ) 的连通图,必须删去 G 的 ( ) 条边才能使得 G 变成一棵树。
正确答案A
解析详情
n 个节点要组成一棵树,应该有 n-1 条边,现有 m 条边,需要删除 m-n+1 条边。
第 9 题(单选题,2 分)
将 2 个红球、1 个蓝球、1 个白球放到 10 个编号不同的盒子中去,每个盒子最多放一个球,有( )种放法。
正确答案B
解析详情
4 个球本来有 种放法,但 2 个红球不可区分,所以要再除以 2。
第 10 题(单选题,2 分)
一个家具公司生产桌子和椅子。现在有 113 个单位的木材。每张桌子要使用 20 个单位的木材,售价是 30 元;每张椅子要使用 16 个单位的木材,售价是 20 元。使用已有的木材
生产桌椅(不一定要把木材用光),最多可以卖( )元钱。
正确答案C
解析详情
枚举桌子的个数,范围是从 0 到 113/20 = 5,用剩余木材求出椅子个数,再算下总价的最大值。
第 11 题(单选题,2 分)
插入排序、冒泡排序、选择排序、快速排序的时间复杂度分别是()。
正确答案A
解析详情
插入排序、冒泡排序、选择排序的时间复杂度均为 ,快速排序的复杂度为 。
第 12 题(单选题,2 分)
以下数据结构中,( )不是线性结构。
正确答案B
解析详情
二叉树是树形结构,不属于线性结构。
第 13 题(单选题,2 分)
以下最短路径算法中,不能处理带有负边权值的是()。
正确答案A
解析详情
Dijkstra 算法只适用于无负权值的单源最短路。Floyd 算法可以处理多源路径,可处理负权值,但时间复杂度高。Bellman-Ford 算法是求含负权图的单源最短路径的一种算法。SPFA 算法可视为在 Bellman-Ford 算法基础上的一种优化。
第 14 题(单选题,2 分)
栈 S 最多能容纳 4 个元素。现有 6 个元素按 1,2,3,4,5,6 的顺序进栈,( )是可能的出栈序列。
正确答案B
解析详情
逐个选项模拟即可。其中选项 C 和 D 的出栈顺序直接做不到(有 “3,1,2” 这种形式的子
序列);选项 A 前 5 个元素入栈需要栈大小为 5。
第 15 题(单选题,2 分)
平面上有三条平行直线,每条直线上分别有 7, 5, 6 个点,且不同直线上的三个点都不在同一条直线上。以这些点为顶点,能组成( )个不同的四边形。
正确答案C
解析详情
假设 3 条平行线 a, b, c 上分别有 7, 5, 6 个点,其中 a 上 7 个点中任取 2 点有 种取法,同理可知 b 上任取 2 点有 10 种取法;c 上任取 2 点有 15 种取法。组成四边形的选法分类如下:
(1) a 上任取 2 点,b 上任取 2 点,可以组成的四边形个数是 ;
(2) a 上任取 2 点,c 上任取 2 点,可以组成的四边形个数是 ;
(3) b 上任取 2 点,c 上任取 2 点,可以组成的四边形个数是 ;
(4) a 上任取 1 点,b 上任取 1 点,c 上取 2 点,可以组成的四边形个数是 ;
(5) a 上任取 1 点,b 上任取 2 点,c 上取 1 点,可以组成的四边形个数是 ;
(6) a 上任取 2 点,b 上任取 1 点,c 上取 1 点,可以组成的四边形个数是 ;
总数为
二、阅读程序(1)
#include <cstdio>
using namespace std;
int findvall(int n) {
int f;
if (n == 0) return 1;
else f = findvall(n / 2);
return n * f;
}
int main() {
int n;
scanf("%d", &n);
printf("%d
", findvall(n));
return 0;
}第 16 题(判断题,2 分)
将 findvall() 中的 if (n == 0) 改成 if (n == 1) 时,对于输入正整数 n,输出不变。 ()
正确答案正确
解析详情
n 是正整数时,只会影响计算 ,而 ,所以再递推一步也是一样。
第 17 题(判断题,2 分)
如果输入正整数 n,输出的值一定小于或等于 n。 ()
正确答案错误
解析详情
,很明显 稍大,累乘结果就会超过 。例如 。
第 18 题(判断题,2 分)
如果输入的 n 是负数,该程序会出现死循环。 ()
正确答案错误
解析详情
负数整除以2只是将绝对值除以2向下取整,所以最后也会变成0,不会发生死循环。
第 19 题(判断题,2 分)
如果多次运行该程序,输入的 n 是单调递增的 int 类型整数,那么每次输出的结果也是一个严格单调递增的数列。 ()
正确答案错误
解析详情
, ,再用归纳法容易证明 在正整数上严格递增。但 n 稍大时 int 很快会溢出,从而产生不规则的数据。这一点有一些争议,但题目写明“int 类型”,可理解为一种暗示,n 的上限可以很大。
第 20 题(单选题,3 分)
若两次输入 n 的值相差 1,输出的结果却是一个正数、一个负数,那么两次输入的 n 可能是下列选项中的()。
正确答案C
解析详情
代入递推式验证一下就行。一般地,输入负数每次递归变号,所以输出符号取决于 的奇偶性。既要奇偶性不同还要相邻,只能是 。
第 21 题(单选题,3 分)
此程序的时间复杂度是()。
正确答案B
解析详情
该程序每次调用,参数除以 2,复杂度为 。
二、阅读程序(2)
#include <cstdio>
#include <cstring>
using namespace std;
int main() {
char str[60];
int len, i, j, chr[26];
char mmin = 'z';
scanf("%s", str); // 保证输入仅含小写字母
len = (int)strlen(str);
for (i = len - 1; i >= 1; i--)
if (str[i - 1] < str[i]) break;
if (i == 0) {
printf("No result!
");
return 0;
}
for (j = 0; j < i - 1; j++) putchar(str[j]);
memset(chr, 0, sizeof(chr));
for (j = i; j < len; j++) {
if (str[j] > str[i - 1] && str[j] < mmin)
mmin = str[j];
chr[str[j] - 'a']++;
}
chr[mmin - 'a']--;
chr[str[i - 1] - 'a']++;
putchar(mmin);
for (i = 0; i < 26; i++)
for (j = 0; j < chr[i]; j++)
putchar(i + 'a');
putchar('
');
return 0;
}第 22 题(判断题,2 分)
输入的字符串长度应该在 1..59 范围内。 ()
正确答案正确
解析详情
字符串都是从 0 开始的,下标 0..59,共 60 个元素,但是字符串都以 '\\0' 结尾,所以可输入的字符数是 1..59。
第 23 题(判断题,2 分)
如果输入的字符数组的所有字符是从大到小排好序的,那么程序会输出 No result!。()
正确答案正确
解析详情
因为这已经是字典序最大状态。从代码层面看,for(i=len-1;i>=1;i--) 循环不会 break,正常退出后 i 值为 0,命中后面的 if。
第 24 题(判断题,2 分)
倒数第7行输出的 值为输入字符串里的 码最小的那个字符。 ( )
正确答案错误
解析详情
实际是找出从 i 到最后的字符中,比 str[i-1] 大的最小的字符。将其换到 str[i-1],这是使字典序变大但变大程度最小的方式。
第 25 题(判断题,2 分)
最后一组(二重)for 循环是把剩下未输出的字符按照从小到大的顺序输出。 ()
正确答案正确
解析详情
chr 数组就相当于未输出字符的计数器,也就是对其计数排序后输出。
第 26 题(单选题,3 分)
如果输入的是 abcdzdcba,则第16行输出的是()。
正确答案A
解析详情
这行代码是输出到从后往前数第一个正序字符(即前一个字符比后一个小)之前的字母,故应为选项 A,因为后面的 dz 是正序的。
第 27 题(单选题,3 分)
如果程序输出是 ffghhggh,则输入有可能是()。
正确答案C
解析详情
可以逐个代入输入用正向的方法验证输出。另根据逻辑,输入的字典序严格小于输出,也可排除选项 A、B、D。
二、阅读程序(3)
#include <bits/stdc++.h>
using namespace std;
int a, mp[101][101];
int t[100003], y[100003], cnt;
int len = 2, dir = 3, die = 0;
const int dx[5] = {0, 0, -1, 0, 1};
const int dy[5] = {0, -1, 0, 1, 0};
int nx = 0, ny = 1, px = 1, py = 2;
int check(int x, int yy) {
if (x < 1 || x > a || yy < 1 || yy > a) return 1;
if (cnt + 1 - mp[x][yy] < len) return 1;
return 0;
}
void work() {
if (die) return;
px += nx;
py += ny;
die = check(px, py);
if (die) return;
mp[px][py] = ++cnt;
}
void show() {
for (int i = 1; i <= a; ++i) {
for (int j = 1; j <= a; ++j) {
if (mp[i][j] != 0 && mp[i][j] >= cnt - len + 1) putchar('o');
else putchar('.');
}
puts("");
}
}
int main() {
memset(mp, 0xf0, sizeof(mp));
mp[1][1] = ++cnt;
mp[1][2] = ++cnt;
int n, m, op, xx;
char s[3];
scanf("%d", &a);
scanf("%d%d", &n, &m);
while (n--) {
scanf("%d%d", &op, &xx);
if (op == 1) {
t[xx] = 1;
scanf("%s", s);
if (s[0] == 'L') y[xx] = 1;
else if (s[0] == 'U') y[xx] = 2;
else if (s[0] == 'R') y[xx] = 3;
else y[xx] = 4;
} else {
t[xx] = 2;
}
}
for (int tm = 1; tm <= m; ++tm) {
if (t[tm] == 1) {
if (y[tm] % 2 != dir % 2) {
dir = y[tm];
nx = dx[y[tm]];
ny = dy[y[tm]];
}
} else if (t[tm] == 2) {
++len;
}
work();
if (die) break;
}
show();
return 0;
}第 28 题(判断题,2 分)
由程序代码可知,贪吃蛇的初始长度为 2,蛇头和蛇尾分别在坐标 [1,2]、[1,1] 处。()
正确答案正确
解析详情
主函数一开始设置的两格。
第 29 题(判断题,2 分)
check 函数是用来检测蛇是否吃到果实的。 ()
正确答案错误
解析详情
根据 check 的第一个 if 看出,是检测蛇是否越界,所以与果实无关。可猜到第二个 if 是检查是否自交。由此可知 mp[i][j] 上留下的数字是最近一次到达该位置的时间,与当前 cnt 之差和 len 比较,即可判定蛇是否撞上自己。
第 30 题(判断题,2 分)
主函数中输入并存储的 y[xx] 表示在第 xx 秒按下了 y 键,y 的取值为 L、U、R、D 之一,分别对应左、上、右、下四个方向按钮。 ()
正确答案正确
解析详情
根据后面 tm 的循环可以验证,y 数组记录的是操作序列。
第 31 题(判断题,2 分)
当输入样例如下所示时,最终程序的运行结果表示贪吃蛇在第9秒过后就死亡了,因此最后贪吃蛇保持的是死亡前(第7秒过后)的位置。 ()
10 10 20 21 22 23 24 25 16R 17D 18L 19U 210
正确答案错误
解析详情
手动模拟即可。实际情况是:贪吃蛇在第9秒后就死亡了,最后贪吃蛇保持的是死亡前(第8秒过后)的位置。
第 32 题(单选题,4 分)
若输入的地图边长为x,共执行n次操作(x>n),则该程序的时间复杂度为()。
正确答案A
解析详情
最后输出地图,复杂度是 ,其他模拟,预处理复杂度都是线性的。
三、完善程序(1)
小 D 在外面游玩,回去时想在 App 上点 KFC,然后带回宿舍。他想选择一家 KFC,取完餐后尽快回宿舍,忽略取餐时间。地图可看作 的网格,其中有一些不可通过的障碍,小 D、KFC、宿舍均可以看作道路,可以通行。小 D 可途经多个 KFC。小 D 可以选择向上、下、左、右四个方向移动,一次移动算一步。求他取到餐并回到宿舍的最少步数。
输入第一行有两个数 n, m。接下来 n 行,每行包含 m 个字符,表示地图。
'S' 表示小 D 的初始位置,
'E' 表示宿舍位置,
'#' 表示障碍物,
1. 表示道路,
K' 表示 KFC。
下面的程序已采用 BFS 算法完成这个问题,试补全程序。
#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int MAXN = 1e3 + 10;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> P;
char s[MAXN][MAXN];
int n, m;
int dir[2][4] = {{1, -1, 0, 0}, {0, 0, 1, -1}};
int dis[2][MAXN][MAXN];
void bfs(int p, int a, int b) {
memset(dis[p], INF, sizeof(dis[p]));
dis[p][a][b] = 0;
queue<pair<P, int>> q;
q.push({{a, b}, 0});
while (!q.empty()) {
int x = q.front().fi.fi, y = q.front().fi.se, d = q.front().se;
q.pop();
for (int i = 0; i < 4; i++) {
int dx = x + dir[0][i], dy = y + dir[1][i];
if (dx < 1 || dy < 1 || dx > n || dy > m || s[dx][dy] == '#') continue;
if (①) {
②;
③;
}
}
}
}
int main(void) {
while (scanf("%d%d", &n, &m) != EOF) {
int ans = INF;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (s[i][j] == 'S') bfs(0, i, j);
else if (s[i][j] == 'E') ④;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (s[i][j] == 'K') ans = ⑤;
if (ans == INF) ans = -1;
printf("%d
", ans);
}
return 0;
}第 33 题(单选题,3 分)
① 处应填()。
dis[p] [dx] [dy] > ddis[p] [dx] [dy] > d+1dis[p] [dx] [dy] < ddis[p] [dx] [dy] < d+1正确答案B
解析详情
找最短路径,发现有一条到 [dx,dy] 点更短的路径,因为走一格需要一个步长,所以要加一。
第 34 题(单选题,3 分)
②处应填( )。
dis[p] [dx] [dy] = ddis[p] [dx] [dy] = d-1dis[p] [dx] [dy] = d+1dis[p] [dx] [dy] = 1正确答案C
解析详情
发现有更短的路径就更新,逻辑同上题一样。
第 35 题(单选题,3 分)
③处应填()。
q.push({{dx,dy},d+1})q.push({{dx,dy},d})q.push({{dx,dy},d-1})q.push({{dx,dy},1})正确答案A
解析详情
发现更短路径后更新该点路径,还需要将节点加入队列,从而可以松弛更新后续节点的路径值。
第 36 题(单选题,3 分)
④处应填()。
bfs(0,j,i)bfs(1,j,i)bfs(0,i,j)bfs(1,i,j)正确答案D
解析详情
搜索时的第一个参数为 0,是以小 D 所在位置作为源点进行搜索。第一个参数为 1,则以宿舍作为源点进行搜索。后两个参数表示 BFS 的起点坐标,所以还是 i,j。
第 37 题(单选题,3 分)
⑤处应填()。
min(ans, dis[0][i][j]+dis[1][i][j])min(ans, dis[0][j][i]+dis[1][j][i])min(ans, dis[0][i][j])min(ans, dis[1][i][j])正确答案A
解析详情
需要的是从小 D 位置到该 KFC 所在点及从宿舍位置到该 KFC 所在点位置距离和的最小值,故应该选择 A。
三、完善程序(2)
(尺取法求区间个数)给定 n 个非负整数 a[1]..a[n],求区间和小于或等于 k 的区间个数,即求使 a[L]+\cdots+a[R] ≤ k 的区间 [L,R] 的个数( )。由于对内存和时间复杂度有要求,本题已经用尺取法写好部分代码,请补全程序。
输入的第一行为两个整数 n, k (1 ≤ n ≤ 1000000, 0 ≤ k ≤ 10000000 000 000 000 000),第二行为 n 个数,表示 a[1] ~ a[n] (0 ≤ a[i] ≤ 1000 000 000)。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mx = 1e6 + 10;
int n, a[mx];
ll k, sum, ans;
int main() {
scanf("%d%lld", &n, &k);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
int r = 0;
for (int i = 1; i <= n; ++i) {
while (r < n) {
if (①) ②;
else break;
}
③;
if (i <= r) ④;
else ⑤;
}
printf("%lld
", ans);
return 0;
}第 38 题(单选题,3 分)
① 处应填( )。
sum+a[r+1] <= ksum+a[r] <= ksum+a[r+1] < ksum+a[r] < k正确答案A
解析详情
题意要求总和 ,先排除选项 C 和 D;r 的初始值为 0,a 数组是从 1 开始的。所以 sum 表示的是 a[1]..a[r] 之和(1 和 r 两端都包含),此处是试探 a[r+1] 能否加入,所以选 A。
第 39 题(单选题,3 分)
②处应填()。
sum += a[r]sum += a[++r]sum += a[r++]sum += a[r+1]正确答案B
解析详情
当符合 sum+a[r+1] <= k 这个条件时,要把 a[r+1] 加入 sum,并且 r 自增,简写就是 a[++r]。
第 40 题(单选题,3 分)
③处应填()。
ans += r-i+1ans += r-ians += r-j-1ans += n-i+1正确答案A
解析详情
r 是使 [i,r] 满足条件的最大的右端点,则与 i 匹配的右端点是 i..r,共 r-i+1 个。
第 41 题(单选题,3 分)
④处应填( )。
sum += a[i]sum = a[r]sum = a[i]sum -= a[i]正确答案D
解析详情
左端点 i 右移之前,将其从 sum 中扣除。i-- 的步骤在 for 循环里。
第 42 题(单选题,3 分)
⑤ 处应填( )。
r = ++ir = i--r = i++r = i正确答案D
解析详情
这种情况出现在数据中有单一的一个数比 k 还大,任何值加上它都会大于 k。此时就会出现 i = r+1 这种空区间情况。其实这种情况不处理也不会有问题(也就是 ④ 和 ⑤ 整个 if 就改成 sum == a[i],初始时 r = 0 也属于这类情况)。但题目已经这样写了,这个分支 ⑤ 里 sum 没有减,所以只能让 r 额外加一 (=i) 以达到同样的效果。具体过程可以用如下数据模拟了解。
58
314102