一、单项选择题
(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)
试卷解析 · 理解每一步
CSPJ-2024-R1
试卷解析总览,可直接查看每题答案与解析。
(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)
32 位 int 类型的存储范围是?( )
正确答案C
32 位有符号 int 按补码表示时,最高位的权值为 ,其余 31 位最大和为 ,所以范围是 -2147483648 到 2147483647。
计算 的结果,并选择答案的十进制值:()
正确答案A
,,,。
因此 。
某公司有 10 名员工,分为 3 个部门:A 部门有 4 名员工、B 部门有 3 名员工、C 部门有 3 名员工。现需要从这 10 名员工中选出 4 名组成一个工作小组,且每个部门至少要有 1 人。问有多少种选择方式?()
正确答案B
4 人覆盖 3 个部门,人数分配只能是 。
多出的 1 人来自 A、B、C 时,方案数分别为 、、,合计 126。
以下哪个序列对应数字 0 至 8 的 4 位二进制格雷码(Gray code)?()
正确答案D
格雷码要求相邻两个码字恰好只有 1 位不同。D 中从 0000 到 0100 的每次相邻变化都只翻转 1 位;题干列出的 8 个码字实际对应 0 至 7,按所给序列应选 D。
记 1KB 为 1024 字节(byte)、1MB 为 1024KB,那么 1MB 是多少二进制位(bit)?()
正确答案D
字节,每字节 8 位,所以共有 位。
以下哪个不是 C++ 中的基本数据类型?( )
正确答案C
int、float 和 char 都是 C++ 的基本数据类型;struct 是定义结构体这种复合数据类型的关键字,本身不是基本数据类型。
以下哪个不是 C++ 中的循环语句?( )
正确答案D
C++ 提供 for、while 和 do-while 三种循环结构,没有 repeat-until 语句。
在 C/C++ 中,(char)('a'+13)与下面的哪一个值相等?()
正确答案B
按题目采用的常见 ASCII 编码,小写英文字母连续,'a' 加 13 就是向后移动 13 个字符位置,得到 'n';再转换为 char 后值不变。
假设有序表中有 1000 个元素,则用二分法查找元素 X 最多需要比较( )次。
正确答案B
二分查找每比较一次将范围缩小约一半。因为 ,最坏情况下最多比较 10 次。
下面的哪一个不是操作系统名字?()
正确答案A
Linux、Windows 和 macOS 都是操作系统;Notepad 是运行在操作系统之上的文本编辑应用程序。
在无向图中,所有顶点的度数之和等于()。
正确答案B
无向图的每条边分别给两个端点贡献 1 度,因此所有顶点度数之和为边数的两倍,即 。
已知二叉树的前序遍历为 ,中序遍历为 ,请问该二叉树的后序遍历结果是?()
正确答案A
前序首元素 A 是根;中序中 A 左侧构成以 B 为根、D 和 E 为左右孩子的子树,右侧构成以 C 为根、F 和 G 为左右孩子的子树。
按“左子树、右子树、根”的后序顺序得到 。
给定一个空栈,支持入栈和出栈操作。若入栈操作的元素依次是 1 2 3 4 5 6,其中 1 最先入栈、6 最后入栈,下面哪种出栈顺序是不可能的?()
正确答案D
按 D 输出 1、3、5 后,栈中从底到顶为 2、4,此时若要输出 2,必须先弹出压在它上面的 4,因此该序列不可能。
其余序列都能通过适时入栈和出栈实现。
有 5 个男生和 3 个女生站成一排,规定 3 个女生必须相邻。问有多少种不同的排列方式?
( )
正确答案A
把 3 个女生视为一个整体,与 5 个男生共 6 个对象,可排列 种;女生内部还有 种排列。
总数为 。
编译器的主要作用是什么?()
正确答案B
编译器分析并翻译高级语言源代码,生成计算机可执行的目标代码或机器代码;它本身不等同于直接执行、调试或运行时内存管理。
1 | #include <iostream>
2 | using namespace std;
3 |
4 | bool isPrime(int n) {
5 | if (n <= 1) {
6 | return false;
7 | }
8 | for (int i = 2; i * i <= n; i++) {
9 | if (n % i == 0) {
10 | return false;
11 | }
12 | }
13 | return true;
14 | }
15 |
16 | int countPrimes(int n) {
17 | int count = 0;
18 | for (int i = 2; i <= n; i++) {
19 | if (isPrime(i)) {
20 | count++;
21 | }
22 | }
23 | return count;
24 | }
25 |
26 | int sumPrimes(int n) {
27 | int sum = 0;
28 | for (int i = 2; i <= n; i++) {
29 | if (isPrime(i)) {
30 | sum += i;
31 | }
32 | }
33 | return sum;
34 | }
35 |
36 | int main() {
37 | int x;
38 | cin >> x;
39 | cout << countPrimes(x) << " " << sumPrimes(x) << endl;
40 | return 0;
41 | }当输入为 “10” 时,程序的第一个输出为 “4”,第二个输出为 “17”。()
正确答案正确
10 以内的素数为 2、3、5、7,共 4 个,元素之和为 ,所以程序输出“4 17”。
若将 isPrime(i) 函数中的条件改为 i <= n / 2,输入 “20” 时,countPrimes(20) 的输出将变为 “6”。()
正确答案错误
把上界扩大为 虽然增加了试除次数,但合数仍能找到因子、素数仍不会找到因子。20 以内仍有 8 个素数,countPrimes(20) 不会变为 6。
sumPrimes 函数计算的是从 2 到 n 之间的所有素数之和。
正确答案正确
sumPrimes 遍历 到 ,仅当 isPrime(i) 为真时执行 `sum += i`,因此累加的正是该范围内所有素数。
当输入为 “50” 时,sumPrimes(50) 的输出为()。
正确答案B
50 以内素数为 2、3、5、7、11、13、17、19、23、29、31、37、41、43、47。
依次相加得到 328,因此 sumPrimes(50) 返回 328。
如果将 for (int i = 2; i * i <= n; i++) 改为 for (int i = 2; i <= n; i++)
输入 “10” 时,程序的输出()。
正确答案A
循环若执行到 `i == n`,任何 都会因 `n % n == 0` 被判为非素数。
因此 2 到 10 的数全部无法通过 isPrime,程序不能正确得到原来的素数个数与和。
1 | #include <iostream>
2 | #include <vector>
3 | using namespace std;
4 |
5 | int compute(vector<int>& cost) {
6 | int n = cost.size();
7 | vector<int> dp(n + 1, 0);
8 | dp[1] = cost[0];
9 | for (int i = 2; i <= n; i++) {
10 | dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i - 1];
11 | }
12 | return min(dp[n], dp[n - 1]);
13 | }
14 |
15 | int main() {
16 | int n;
17 | cin >> n;
18 | vector<int> cost(n);
19 | for (int i = 0; i < n; i++) {
20 | cin >> cost[i];
21 | }
22 | cout << compute(cost) << endl;
23 | return 0;
24 | }当输入的 cost 数组为 时,程序的输出为 15。()
正确答案正确
初值为 ,随后 、。
函数返回 。
如果将 dp[i-1] 改为 dp[i-3],程序可能会产生编译错误。()
正确答案错误
代码语法和类型仍然合法,通常可以通过编译;但循环第一次取 `dp[i-3]` 时 ,访问的是 `dp[-1]`,会造成越界访问和未定义行为。
程序总是输出 cost 数组中最小的元素。()
正确答案错误
程序根据相邻状态计算到达各位置的累计最小花费,而不是直接求数组最小值。例如 cost 为 时输出 15,但数组最小元素是 10。
当输入的 cost 数组为 时,程序的输出为()。
正确答案A
由 依次得到 。
最终返回 。
如果输入的 cost 数组为 ,程序的输出为()
正确答案B
初值 ,继续递推得到 。
函数返回 。
若将代码中的 min(dp[i-1], dp[i-2]) + cost[i-1] 修改为 dp[i-1] + cost[i-2], 输入 cost 数组为 {5, 10, 15} 时,程序的输出为()。
正确答案A
修改后 。对 ,有 、、,最终返回 。
1 | #include <iostream>
2 | #include <cmath>
3 | using namespace std;
4 |
5 | int customFunction(int a, int b) {
6 | if (b == 0) {
7 | return a;
8 | }
9 | return a + customFunction(a, b-1);
10 | }
11 |
12 | int main() {
13 | int x, y;
14 | cin >> x >> y;
15 | int result = customFunction(x, y);
16 | cout << pow(result, 2) << endl;
17 | return 0;
18 | }当输入为 “2 3” 时,customFunction(2, 3) 的返回值为 “64”。()
正确答案错误
customFunction(2,3) 会把 2 累加 4 次,返回 ;64 是 main 中对返回值平方后的最终输出,不是函数返回值。
当 b 为负数时,customFunction(a, b) 会陷入无限递归。()
正确答案正确
递归只在 `b == 0` 时终止;若 b 初始为负数,每次执行 `b-1` 会离 0 越来越远,递归无法正常结束并最终导致栈耗尽。
当 b 的值越大,程序的运行时间越长。()
正确答案正确
对非负 b,每层递归把 b 减 1,直到 0,共进行与 b 成正比的调用,时间复杂度为 ;b 越大,运行时间通常越长。
当输入为 “5 4” 时,customFunction(5, 4) 的返回值为()。
正确答案B
customFunction(a,b) 对非负 b 返回 。因此 customFunction(5,4) 返回 。
如果输入 x=3 和 y=3,则程序的最终输出为()。
正确答案C
customFunction(3,3) 返回 ,main 随后计算 `pow(12, 2)`,最终输出 144。
若将customFunction函数改为“return a + customFunction(a-1, b-1);”,并输入“3 3”,则程序的最终输出为()。
正确答案D
修改后 customFunction(3,3) 展开为 ,其中基例 customFunction(0,0) 返回 0。
main 输出 。
问题:给定一个正整数 n,希望判断这个数是否为完全平方数,即存在一个正整数 x 使得 x 的平方为 n。
试补全程序。
#include<iostream>
#include<vector>
using namespace std;
bool isSquare(int num) {
int i = ①;
int bound = ②;
for (; i <= bound; ++i) {
if (③) {
return ④;
}
}
return ⑤;
}
int main() {
int n;
cin >> n;
if (isSquare(n)) {
cout << n << " is a square number" << endl;
} else {
cout << n << " is not a square number" << endl;
}
return 0;
}①处应填()
1234正确答案A
题目要求寻找正整数 x,最小候选值是 1,因此循环变量 i 应从 1 开始,才能覆盖 。
②处应填()
(int)floor(sqrt(num))-1(int)floor(sqrt(num))floor(sqrt(num/2))-1floor(sqrt(num/2))正确答案B
若 num 是完全平方数,它的正整数平方根必为 ;枚举到 即可覆盖唯一可能的整数根,同时无需检查更大的 i。
③处应填()
num = 2 * inum == 2 * inum = i * inum == i * i正确答案D
完全平方数的定义是存在整数 i 使 ,因此条件应写为 `num == i * i`。
④处应填()
num = 2 * inum == 2 * itruefalse正确答案C(另接受:A)
进入该分支说明已经满足 `num == i * i`,即确认 num 是完全平方数,所以 isSquare 应立即返回 true。
⑤处应填( )
num = i * inum != i * itruefalse正确答案D
循环检查完 到 仍未命中 `num == i * i`,说明不存在整数平方根,应返回 false。
给定三根柱子,分别标记为 A、B 和 C。初始状态下,柱子 A 上有若干个圆盘,这些圆盘从上到下按从小到大的顺序排列。任务是将这些圆盘全部移到柱子 C 上,且必须保持原有顺序不变。在移动过程中,需要遵守以下规则:
1. 只能从一根柱子的顶部取出圆盘,并将其放入另一根柱子的顶部。
2. 每次只能移动一个圆盘。
3. 小圆盘必须始终在大圆盘之上。
试补全程序。
#include <iostream>
#include <vector>
using namespace std;
void move(char src, char tgt) {
cout << "从柱子" << src << "挪到柱子" << tgt << endl;
}
void dfs(int i, char src, char tmp, char tgt) {
if (i == ①) {
move(②);
return;
}
dfs(i - 1, ③);
move(src, tgt);
dfs(⑤, ④);
}
int main() {
int n;
cin >> n;
dfs(n, 'A', 'B', 'C');
}①处应填()
0123正确答案B
当只剩 1 个圆盘时,可以直接从 src 移到 tgt,无需继续分解,因此递归终止条件应为 `i == 1`。
②处应填()
src, tmpsrc, tgttmp, tgttgt, tmp正确答案B
在 `i == 1` 的基例中,唯一的圆盘应直接从源柱 src 移到目标柱 tgt,因此调用 `move(src, tgt)`。
③处应填()
src, tmp, tgtsrc, tgt, tmptgt, tmp, srctgt, src, tmp正确答案B
移动最大圆盘前,要先把上方 个圆盘从 src 移到 tmp,此时原 tgt 充当辅助柱。
按函数参数 `(src, tmp, tgt)` 的角色传入应为 `src, tgt, tmp`。
④处应填()
src, tmp, tgttmp, src, tgtsrc, tgt, tmptgt, src, tmp正确答案B
最大圆盘移到 tgt 后,要把暂存在 tmp 的 个圆盘移到 tgt,此时 src 充当辅助柱。
因此三根柱子参数应依次为 `tmp, src, tgt`。
⑤处应填()
01i - 1i正确答案C
移动最大圆盘后,tmp 上还剩 个较小圆盘需要递归移到 tgt,所以调用规模应为 `i - 1`。