2024 csp-j 模拟卷

考生注意事项:
满分 100 分。请在答题纸上作答,写在试题纸上的一律无效。
不得使用任何电子设备(如计算器、手机、电子词典等)或查阅任何书籍资料。
一、 单项选择题(共 15 题, 每题 2 分, 共计 30 分; 每题有且有一个正确选项)
1. 有一个 int 类型的变量 a,以下表达式得到的结果和 a/2 一致是 ( )。
A. a << 1
B. a >> 1
C. a | 1
D. a ^ 1
答案解析:正确答案 B。
右移操作能实现求变量的一半。
2. 以下叙述正确的是 ( )。
A. 在一个程序中,允许使用任意数量的#include 命令行
B. 在包含文件中,不得再包含其他文件
C. #include 命令行不能出现在程序文件的中间
D. 虽然包含文件被修改了,包含该文件的源程序也可以不重新进行编译和连接
答案解析:正确答案 A。
预处理中文件包含的概念,包含文件中可以包含其他文件, B 选项错误,
#include 可以出现在程序文件的中间, C 选项错误,包含文件被修改了,包
含该文件的源程序必须重新进行编译和连接。
3. 有 2 名老师和 4 名获奖学生排成一排拍照,如果老师不能站在队伍两端则有
( )种排队方式。
A. 288
B. 256
C. 216
D. 312
答案解析:正确答案 A。
先排列4个学生一共有 A 4 4 种排列方式,先让其中一个老师站在已有的队伍中间,
有三个空位,3 种站法。再让另一个老师站在 4 个空位中的一个,有 4 种,所
以一共有 24*3*4=288 种站法。
4. 将 6 相同的书分给 3 个人,每个人至少有一本,一共有( )种分法。 A. 6
B. 10
C. 3
D. 12
答案解析:正确答案 B。
每个人必须分一本,所以一个人手里先拿走一本,剩下 3 本书分给三个人有三
种分法,3、0、0,2、1、0,1、1、1,其中 3、0、0 有 3 种情况,2、1、0 有
3*2*1=6 种,1、1、1 只有 1 种,加起来一共有 10 种。
5. 下列说法不正确的是 ( )。
A. RAM 是与中央处理器直接交换数据的内部存储器,可以随时读写而且速度很
B. CPU 的主要功能是解释计算机指令以及处理计算机软件中的数据
C. ROM 只要存储了就无法被修改或删除,数据不会因为电源关闭而消失
D. Cache 的访问速度一般比 RAM 的访问速度慢
答案解析:正确答案 D。
Cache 的访问速度一般比 RAM(随机存储器)快。
6. 下面的四种排序,其排序的稳定性与其他选项中的排序不同的是?( )
A. 插入排序
B. 冒泡排序
C. 归并排序
D. 快速排序
正确答案:D
选择排序、快速排序、希尔排序、堆排序是不稳定的排序算法,
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
故 D 对,A、B、C 错。
知识点:排序算法稳定性
7. 下列选项中的排序算法,空间复杂度最高的是?( )
A. 归并排序
B. 快速排序
C. 选择排序
D. 插入排序
正确答案:A
知识点:复杂度
8. 下列选项中能用二分法进行查找的是?( )
A. 数组
B. 二叉链表
C. 单链表
D. 双链表
答案解析:
正确答案:A
能够进行二分查找的条件:
1 顺序存储
2 有序
数组满足这两个条件,故 A 对,B、C、D 错。
知识点:二分
9. 有一个图的邻接表,如下图,从顶点 a 出发的话,那么广度优先遍历的结果
是?( )
A. abdc
B.acdb
C.abcd
D.adbc
正确答案:C
给定邻接表,从顶点 a 出发,直接读取邻接表第一行,a b c d,a b c d 为
顶点全集。
知识点:图的广搜
10. 有五个叶结点,权值依次 27,10,18,5,25,将这 5 个叶结点构成哈夫曼树
为的话,则带权路径长度是( )。
A. 85
B. 185
C. 215
D. 300
正确答案:C
哈夫曼树构成过程:
1 将 5 个结点放入集合 T={27,10,18,5,25};
2 从 T 中取出没有双亲且权值最小的两个结点,进行合并成新的一棵树,并将
新树 t1 插入到集合中,并将左右子树从集合中删除;
3 重复 2 操作,直到集合 T 中只剩下一棵树;
注意:通常权值小的是左子树,大的右子树,左小右大,如果两个结点的权值
相等,先出现的结点为左子树,新生成的结点按照生成顺序排在所有叶结点的
后面 27,10,18,5,25
5 和 10 合并成 15,将 15 放入集合 T 中,{27,15,18,25}
15 和 18 合并成 33,将 33 放入集合 T 中,{27,33,25}
此时,将 25 和 27 合并成 52,将 52 放入集合 T 中{33,55}
目前情况
树的带权路径长度为(根节点到叶结点的路径长度*叶结点的权值)对每个叶节
点的和。
计算路径长度:5*3+10*3+15*2+18*2+25*2+27*2=215
知识点:贪心哈夫曼树
11. 以下有关线性结构和非线性结构说法正确的是( )。
A. 线性结构与非线性结构针对的是数据的物理结构。
B. 栈、队列、链表和集合结构都属于线性结构。
C. 像树和图这种元素与元素之间是多对多关系的结构都属于非线性结构。
D. 线性结构要求每个元素最多只有一个直接前驱和直接后继。
正确答案:D
解析:线性结构与非线性结构针对的是数据的逻辑结构,主要用来描述数据与
数据之间关系;栈、队列和链表属于线性结构,集合结构属于非线性结构;树
和图属于非线性结构,树中元素是一对多的关系,图是多对多的关系;线性结
构要求每个元素最多只有一个直接前驱和直接后继,非线性结构每个元素可以
有不止一个直接前驱和直接后继。所以 D 选项正确。
12. 已知表达式的前缀表达式为- * / - + / * 4 6 12 2 2 2 4 1,其后缀表
达式为( )。
A. 4 6 * 12 / 2 + 2 - 2 4 * 1 - /
B. 4 6 * 12 2 + 2 - / 2 / 4 * 1 -
C. 4 6 * 12 / 2 + 2 2 / 4 * - 1 -
D. 4 6 * 12 / 2 + 2 - 2 / 4 * 1 -
正确答案:D
解析:前缀表达式为中缀表达式按计算顺序加上小括号之后,把运算符放到相
应小括号前面,再把小括号删除得到的,该前缀表达式对应的中缀表达式为 (4*6/12+2-2)/2*4-1,中缀转后缀表达式为按计算顺序加上小括号之后,把
运算符放到相应小括号后面,再把小括号删除,转后缀表达式为 4 6 * 12 / 2
+ 2 - 2 / 4 * 1 -,所以 D 选项正确。
13. 若使用数组模拟普通队列,且 front 表示队首元素位置,rear 表示队尾元素
的下一个位置,以下哪一个选项可以获取队列中的元素个数( )。
A. rear
B. rear - front - 1
C. rear - front + 1
D. rear - front
正确答案:D
解析:在普通队列中,所有元素的范围为 front ~ rear - 1,元素个数为 rear
- 1 - front + 1 = rear - front。
14. 已知二叉树后序序列为 HDAEIGKFBC,中序序列为 DHAECBGIFK,则先序序列
为( )。
A. CEADHBFKIG
B. CEADHBFGIK
C. CBFGIKEADH
D. CBFKGIEADH
正确答案:B
解析:根据后序序列最后一个元素可以确定出根结点为 C,在中序中可以找到
左子树节点为 DHAE,右子树节点为 BGIFK,对于左右子树,根据左右子树的后
序和中序序列可以确定左右子树的节点分布,从而得到整棵二叉树,
根据画出的二叉树可以得到先序序列为 CEADHBFGIK,所以 B 选项正确。
15. 存在一个连通图,其边集为 E={(A,B),(A,C),(A,D),(C,D),(D,E)},若只删
除 1 个点 v,使得该连通图变成非连通图,则可选取的 v 的个数为( )。
A. 1
B. 2
C. 3
D. 4 正确答案:B
解析:根据边集可画出该连通图为:
由图可知,删除 A 点或 D 点后,图会变成一个非连通图,所以 B 选项正确。
二、阅读程序 (程序输入不超过数组或字符串定义的范围,判断题正确填√,错误
填 x; 除特殊说明外,判断题 1.5 分,选择题 3 分,共计 40 分)

(1)

01 #include <iostream> 
02 #include <cmath> 
03 using namespace std; 
04 long long m,n,ans; 
05 int z(int n,int m){ 
 06 return n%m ? z(m,n%m) : m; 
 07 } 
08 
 09 int main() { 
10 cin >> m >> n; 
 11 n *= m; 
 12 for(long long i = 1;i <= sqrt(n);i++){ 
 13 if(n%i==0 && z(i,n/i)==m) ans += 1; 
 14 } 
 15 cout<<ans; 
 16 return 0; 
17 }
假设输入的所有数都为不超过 1000 的正整数,完成下面的判断题和单选题:
判断题
16. 当输入为“3 60”时,输出为“3”。( )
17. 将第 12 行的 for 循环的大括号去掉,代码也能正常运行。( )
18. (2 分) 把第 12 行 for 循环的条件改为“i<=n”,得到的结果是原有结果的两倍。
( )
单选题 19. 当输入为“2 60”时,输出为( )。
A. “2” B. “3” C. “4” D. “5”
20. 当输入为“12 3”时,输出为( )。
A. “2” B. “1” C. “0” D. “3”
答案:16. × 17. √ 18. × 19. C 20. C
解析:16 题运行的结果是错误的,得到的结果为 2,在 i 等于 3 和 12 的时候满足。
17 题是正确的,循环内只有一条语句,可以不使用大括号。18 题错误,当输入的 m
和 n 相等时,更改条件的结果是一致的。19 题选择选项 C。n 的值为 120 在 i 的值
为 2,6,10 时满足情况。20 题选择选项 C。i 循环的范围是从 1 到 6,其中不会出
现最大公约数为 12 的数字,最大公约数不可能比其中一个数字大
(2)
#include <iostream> 
02 #include <vector> 
03 using namespace std; 
04 vector<string> split(string s, char c) { 
05 vector<string> res = {}; 
06 int i = 0; 
07 for (int j = 0; j < s.length(); j++) { 
08 if (s[j] == c) { 
09 string temp = s.substr(i, j - i); 
10 res.push_back(temp); 
11 i = j + 1; 
12 } 
13 } 
14 res.push_back(s.substr(i, s.length() - i)); 
15 return res; 
16 } 
17 bool isvalid(string s) { 
18 vector<string> v = split(s, '.'); 
19 if (v.size() != 4) 
20 return false; 
21 for (int i = 0; i < v.size(); i++) { 
22 string cur = v[i]; 
23 int len = cur.length(); 
24 if (len == 0 || len > 3) 
25 return false; 
26 if (cur[0] == '0' && len != 1) 
27 return false; 
28 for (int j = 0; j < len; j++) { 
29 if ((cur[j] >= '0' && cur[j] <= '9') || (cur[j] >= 
'a' && cur[j] <= 'f') || (cur[j] >= 'A' && cur[j] <= 'F')) 
30 continue; 
31 else 
32 return false; 
33 } 
34 if (stoi(cur) < 0 || stoi(cur) > 255) 
35 return false; 
36 } 
37 return true; 
38 } 
39 string strp; 
40 int main() { 
41 while (cin >> strp && strp != "endl") { 
42 bool res = isvalid(strp); 
43 cout << res ? "Yes" : "No"; 
44 cout << endl; 
45 } 
46 return 0; 
47 }
判断题
21. 将第 7 行代码的 s.length() 修改成 s.sizeof(),不影响程序的正确执行。
( )
22. 去掉 14 行代码,程序无法正确运行结果。( )
23. 将 26 行代码 len != 1 替换成 len > 1,程序无法运行出正确的结果。 ( )。
单选题
24. 当输入 192.168.31.010,程序的输出结果是( )。
A. Yes B. No C. 1 D. 0
25. 当输入 192.256.1.18,程序的输出结果是( )。
A. Yes B. No C. 1 D. 0
26. 当输入
175.18.254.10
192..168.8
123.a.88.09
255.0.00.251
0.0.0.0
endl
程序的输出结果是( )。
A. 1 0 0 1 1 B. 1 1 0 0 1 C. 1 0 0 0 1 D. 0 0 0 1 1 答案:21. × 22. √ 23. × 24. D 25. D 26. C
解析:
21 错误,s.length()是获取字符串的长度,sizeof()函数是用来计算所占的
字节数;
22 正确,该行代码是将输入的 ip 地址字符串的最后一组数字截取出来存储到
res 中,如果删除该行代码,就少 ip 地址的最后一组;
23 错误,判断 IP 地址的每一组中的 0 的个数,如果第一个是 0,保证不能存
在多个 0,比如 00,只需保证长度大于 1 就可以;
24 分析程序,该程序实现的功能是检测输入的 ip 地址是否合法的,重点
isvalid 函数,用来检测各种满足正确 ip 地址的条件
1 ip 地址有四组数字组成
2 每个字串,字串长度为 0、或者大于 3,不合法
3 非 0 字串是有前置 0,不合法
4 字串中包含除数字外的字符,不合法
5 输入的 ip 字符串长度越界,不合法
192.168.31.010 中的第四组,不满足条件 3,正确的应该是 01,在代码 43
行使用三目运算进行结果的输出,它的优先级低于<<,会直接输出 res 的值,bool
类型的 res 会自动升级为 int 类型的 0,答案是 D。
25 解析同上,192.256.1.18 中的第二组数字 256 超过了最大值限制 255,不
合法,输出 0,答案选 D;
26 175.18.254.10 合法 1
192..168.8 不合法 不够四组
123.a.88.09 不合法 第二组含有字母
255.0.00.251 不合法 第三组有前置 0
0.0.0.0 合法
输出结果是: 1 0 0 0 1
答案选 C;
(3)
01 #include <iostream> 
02 #include <set> 
03 #include <vector> 
04 using namespace std; 
05 int n, k, v[21]; 
06 set<int> st; 
07 
08 void f(int num, int sum, int idx){ 
09 if(num == k){ 
10 st.insert(sum); 
11 return; 
12 } 
13 for(int i = idx; i < n; i++){ 
14 f(num + 1, sum + v[i], i + 1); 
15 } 
16 } 
17 int main(){ 
18 cin >> n >> k; 
19 for(int i = 0; i < n; i++){ 
20 cin >> v[i]; 
21 } 
22 f(0, 0, 0); 
23 cout << st.size(); 
24 return 0; 
25 }
判断题
27. 该程序是从 n 个整数中任选 k 个整数,输出选法的数量。( )
28. 如果将第 13 行的 idx 修改为 0,程序结果不变。( )
29. 如果将第 11 行删除,程序结果不变。( )
单选题
30. 当输入为 3 2 1 2 2 时,输出为( )。
A. 1 B. 2 C. 3 D. 4
31. 当输入为 5 3 1 2 4 6 7 时,第 14 行的执行次数为( )。
A. 10 B. 15 C. 20 D. 25
32. 当输入为 5 4 1 2 1 5 2 时,输出为( )。
A. 1 B. 2 C. 3 D. 4
答案:27. × 28. × 29. √ 30. B 31. D 32. C
解析:该程序为从输入的 n 个整数中任选 k 个整数进行相加求和,使用 set 存储和,
去重后输出所有可能的不同和出现的次数。
27.该程序使用 set 去重了,所以输出的是不同和出现的次数,所以错误。
28.idx 修改为 0 之后,k 个位置选数时每个位置都从所有数中选,所以会出现同一
数字使用多次,所以结果可能会变,所以错误。
29.将 11 行的 return 删除后,不影响 k 个数选完后统计结果,所以对结果没有影
响,所以正确。
30.输入为 3 2 1 2 2,3 个数选 2 个求和,求不同和出现次数,不同和为 1+2=3、
2+2=4,总共 2 个,所以 B 选项正确。
31.输入为 5 3 1 2 4 6 7,5 个数选 3 个,第 1 个位置会放 1 2 4 6 7 各一次,
第 1 个位置 1,第 2 个位置 2 4 6 7 各一次,第 2 个位置 2,第 3 个位置 4 6 7 各 一次,按照此规律推导,第 14 行的递归调用总执行次数为 25 次。
32.输入为 5 4 1 2 1 5 2,
5 个数选 4 个,不同的和的个数为 1+2+1+5=9、1+2+1+2=6、
1+2+5+2=10 这 3 个,所以 C 选项正确。
三、完善程序(单选题,每小题 3 分,共计 30 分)
(1)(区间查找) 问题:给你一个遵循递增原则的序列,和一个目标值 target。请
你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标
值 target,返回 [-1, -1]。
试补全程序。
33. ①处填写的代码为( )
A. start B. end C. last D. mid
34. ②处填写的代码为( )
A. start>end B. start!=end
C. start <= end D. start>=middle
35. ③处填写的代码为( )
A. start B. end C. last D. mid
36. ④处填写的代码为( )
A. serchright(a,target,1)
B. serchleft(a,n,target)
C. serchleft(a,n,1)
D. serchleft(a,target,n)
37. ⑤处填写的代码为( )
A. "%d,%d",l,r
B. "[%d,%d]",l,r
C. "[%d,%d]",r,l
D. "%d,%d",l-1,r+1
解析:
答案:33. A 34. C 35. C 36. D 37. B
题目描述数组是有序的,然后要求找等于 target 的第一个位置和等于 target 的最
后一个位置。
找等于 target 的一个位置可以等价于求>= target 的第一个位置
找等于 target 的最后一个位置可以等价于求>= target+1 的第一个位置 - 1
因为问题的难点就变成了如何快速找到大于等于 target 的第一个元素位置。
假设数组还有没有被标记成红色或蓝色的数组左端点为 left, 数组右端点为
right.
分成两次去分别查找第一次出现的位置 first 及最后出现的位置 last。
查找左端点时,如果中点元素等于 target, 则可以说明[left, mid]的元素仍会
出现目标值 target, 那么将 right 重新指向[left, mid]的右端点,即 right =
mid - 1
只要 left <= right, 就一直指向上述操作。在每次出现目标时记录对应位置,循
环结束后第一次和最后一次出现的位置分别记录在 first 和 last 当中
(2)(cc 冒险) 问题:cc 在进行一次森林大冒险,冒险的路程是一条曲折幽暗的森
林之路,在第 i 个位置上会发生一件事情,用(t i , x i )表示。
若 t i = 1,则表示这里有一个 x i 的神奇魔力的蘑菇。cc 可以选择捡起放自己的背
包里也可以选择不捡起;若 t i = 2,则表示这里有一个 x i 可怕的怪兽,需要用一
个 x i 魔力的蘑菇才能打败它。
你需要求出,在 cc 能打败所有怪兽的情况下,每个时刻手中的蘑菇数的最大值最 小是多少。若不能打败所有怪兽输出-1。
试补全程序

 

38. ①处应该填( ) A. st[x[i]].push_back(i) B. st[x[i]].push(i)
C. st[x[i]].push_front(i) D. st[x[i]].push_top(i)
39. ②处应该填( )
A. cout << "-1";return 0; B. cout<<"-1"
C. return 0; D. return 0;cout<<"-1"
40. ③处应该填( )
A. st[x[i]].pop_top() B. st[x[i]].pop_front()
C. st[x[i]].pop_back() D. st[x[i]].pop()
41. ④处应该填( )
A. break B. maxn = max(maxn, cnt)
C. t[i]=1 D. cnt+=maxn
42. ⑤处应该填( )
A. cnt-- B. cnt++ C. t[i]=1 D. t[i]=0
答案:38. B 39. A 40. D 41. B 42. A
解析:可以发现一个蘑菇无论什么时候拿被使用掉的时间都是不会变的,
所以如果我们想让一个蘑菇在背包里待得时间尽可能的短就要让它尽可能的被晚拿
起来,于是我们就可以想到使用栈存下每一瓶同类的蘑菇分别出现的时间,此时每
遇到一只怪物那么它对应的栈顶就是最晚出现的蘑菇,使用该蘑菇并打上标记。
如果栈空则说明蘑菇不够,cc 就完了。最后统计每时每刻背包容量最大值输出即可。
38.B 考察 stl 中栈的存储方式,应该 push()方法。
39.A st[x[i]].size() <= 0 代表蘑菇不够的时候,根据题目要求要输出-1,同
时需要结束程序运行 return 0;
40.D flag[st[x[i]].top()] = 1;阅读程序这段代码告诉我们打上标记,记为使
用该蘑菇,那么就要给这个蘑菇出栈,蘑菇被用掉了,stl 中 stack 出栈的操作是
pop()方法。
41.B flag[i] > 0 是表示背包里多进一个蘑菇,我们要将 cnt 计数加一同时根
据题目要求来更新 maxn 的值
42.A t[i] == 2 表示用掉一个蘑菇,那应该让 cnt 计数减去 1
记得点赞加关注^-^
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值