单选题解析
第 1 题
32 位 int 类型的存储范围是(C)?
A. -2147483647 ~ +2147483647
B. -2147483647 ~ +2147483648
C. -2147483648 ~ +2147483647
D. -2147483648 ~ +2147483648
解析:32 位 int 类型范围是从 -2³¹ 到 2³¹ - 1,即 -2147483648 到 2147483647。
第 2 题
计算
的结果,并选择答案的十进制值:(A)
A. 13
B. 14
C. 15
D. 16
解析:直接算。
第 3 题
某公司有 10 名员工,分为 3 个部门:A 部门有 4 名员工,B 部门有 3 名员工,C 部门有 3 名员工。现需要从这 10 名员工中选出 4 名组成一个工作小组,且每个部门至少要有 1 人。问有多少种选择方式?(B)
A. 120
B. 126
C. 132
D. 238
解析:分为如下几种情况
情况1:A选1人,B选1人,C选2人
C(4, 1) × C(3, 1) × C(3, 2) = 4 × 3 × 3 = 36
情况2:A选1人,B选2人,C选1人
C(4, 1) × C(3, 2) × C(3, 1) = 4 × 3 × 3 = 36
情况3:A选2人,B选1人,C选1人
C(4, 2) × C(3, 1) × C(3, 1) = 6 × 3 × 3 = 54
ans = 36 + 36 + 54 = 126
故答案选B。
第 4 题
以下哪个序列对应数字 0 至 8 的 4 位二进制格雷码(Gray code)?(D)
A. 0000, 0001, 0011, 0010, 0110, 0111, 0101, 1000
B. 0000, 0001, 0011, 0010, 0110, 0111, 0100, 0101
C. 0000, 0001, 0011, 0010, 0100, 0101, 0111, 0110
D. 0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100
解析:格雷码(Gray Code)是一种二进制循环码,其特点是相邻的两个数之间仅有1位二进制数不同(最后一个格雷码和第一个格雷码也仅相差1位)。
选项A:最后一个应该是0100,这里是1000;
选项B:第7个应该是 0101,这里是 0100;
选项C:第5个应该是 0110,这里是 0100;
选项D:正确。
第 5 题
记 1KB 为 1024 字节(byte),1MB 为 1024KB,那么 1MB 是多少二进制位(bit)?(D)
A. 1000000
B. 1048576
C. 8000000
D. 8388608
解析:
(1MB = 1024KB;1KB = 1024byte;1byte = 8bit。) 1MB = 1024KB = 1024 × 1024byte = 1024 × 1024 × 8bit = 8388608bit,故选D。
第 6 题
以下哪个不是 C++ 中的基本数据类型?(C)
A. int
B. float
C. struct
D. char
解析:struct不是基本数据类型。
第 7 题
以下哪个不是 C++ 中的循环语句?(D)
A. for
B. while
C. do-while
D. repeat-until
解析:repeat-until不是C++中的循环语句。
第 8 题
在 C/C++ 中,(char)(‘a’ + 13) 与下面的哪一个值相等?(B)
A. ‘m’
B. ‘n’
C. ‘z’
D. ‘l’
解析:(char)(‘a’ + 13) 与’n’相等。
第 9 题
假设有序表中有 1000 个元素,则用二分法查找元素 X 最多需要比较(B)次。
A. 25
B. 10
C. 7
D. 1
解析:找到最小的整数n,使2n >= 1000,n = 10。
第 10 题
下面的哪一个不是操作系统名字?(A)
A. Notepad
B. Linux
C. Windows
D. macOS
解析:Notepad是记事本(Win上的应用程序),其余为操作系统。
第 11 题
在无向图中,所有顶点的度数之和等于(B)。
A. 图的边数
B. 图的边数的两倍
C. 图的顶点数
D. 图的顶点数的两倍
解析:一条边能够给相连的两个顶点各增加度数1。画图举例:
。
第 12 题
已知二叉树的前序遍历为 [A,B,D,E,C,F,G],中序遍历为 [D,B,E,A,F,C,G],请问该二叉树的后序遍历结果是?(A)
A. [D,E,B,F,G,C,A]
B. [D,E,B,F,G,A,C]
C. [D,B,E,F,G,C,A]
D. [D,B,E,F,G,A,C]
解析:
。
第 13 题
给定一个空栈,支持入栈和出栈操作。若入栈操作的元素依次是 1 2 3 4 5 6,其中 1 最先入栈,6 最后入栈,下面哪种出栈顺序是不可能的?(D)
A. 6 5 4 3 2 1
B. 1 6 5 4 3 2
C. 2 4 6 5 3 1
D. 1 3 5 2 4 6
解析:
选项 A:
按照它们入栈的相反顺序出栈元素。
选项 B:
先出栈1,然后出栈剩余元素的相反顺序。
选项 C:
先出栈2,然后将3, 4, 5, 6入栈,出栈4和6,然后出栈5,接着出栈3,最后出栈1。
选项 D:
这个顺序是不可能的。
因此选D。
第 14 题
有 5 个男生和 3 个女生站成一排,规定 3 个女生必须相邻。问有多少种不同的排列方式?(A)
A. 4320 种
B. 5040 种
C. 3600 种
D. 2880 种
解析:
将3女生视为一个整体,女生排列方案有P(3, 3) = 6种;
5个男生排列方案有P(5, 5) = 120种;
把3个女生一起“插”在男生队伍里,有C(6, 1) = 6种插法。
ans = 6 × 120 × 6 = 4320种,所以选A。
第 15 题
编译器的主要作用是什么?(B)
A. 直接执行源代码
B. 将源代码转换为机器代码
C. 进行代码调试
D. 管理程序运行时的内存
解析:编译器的主要作用是将源代码转换为机器代码。
阅读程序第一题解析
#include <iostream>
using namespace std;
bool isPrime(int n) {
if (n <= 1) {
return false;
}
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
int countPrimes(int n) {
int count = 0;
for (int i = 2; i <= n; i++) {
if (isPrime(i)) {
count++;
}
}
return count;
}
int sumPrimes(int n) {
int sum = 0;
for (int i = 2; i <= n; i++) {
if (isPrime(i)) {
sum += i;
}
}
return sum;
}
int main() {
int x;
cin >> x;
cout << countPrimes(x) << " " << sumPrimes(x) << endl;
return 0;
}
程序分析
isPrime 函数用于判断一个数是否为质数。countPrimes 和 sumPrimes 函数的结构非常相似,但它们的功能有所不同:
- countPrimes:统计从 2 到 n 之间的质数个数。
if (isPrime(i)) {
count++;
}
- sumPrimes:计算从 2 到 n 之间的所有质数之和。
if (isPrime(i)) {
sum += i;
}
题目解析
判断题
- 当输入为 10 时,程序的第一个输出为 4 ,第二个输出为 17。(正确)
解析:2 到 10 之间的质数有【2, 3, 5, 7】,共 4 个,它们的和为 2 + 3 + 5 + 7 = 17。 - 若将 isPrime(i) 函数中的条件改为 i<=n/2,输入 20 时,countPrimes(20) 的输出将变为 6。(错误)
解析:即使将条件改为 i <= n / 2,质数的判断逻辑不会改变,因此输出不会改变。 - sumPrimes 函数计算的是从 2 到 n 之间的所有质数之和。(正确)
解析:该说法正确,如上文所述。
单选题
- 当输入为 50 时,sumPrimes(50) 的输出为(B)。
A. 1060
B. 328
C. 381
D. 275
解析:2 到 50 之间的质数有【2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47】,它们的和为 2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 + 31 + 37 + 41 + 43 + 47 = 328。 - 如果将 for (int i = 2; i * i <= n; i++) 改为 for (int i = 2; i <= n; i++),输入 10 时,程序的输出(A)。
A. 将不能正确计算 10 以内质数个数及其和
B. 仍然输出 4 和 17
C. 输出 3 和 10
D. 输出结果不变,但运行时间更短
解析:小心踩坑!函数会把合数(除1以外)也判断为质数,不能正确计算 10 以内质数个数及其和。
阅读程序第二题解析
#include <iostream>
#include <vector>
using namespace std;
int compute(vector<int>& cost) {
int n = cost.size();
vector<int> dp(n + 1, 0);
dp[1] = cost[0];
for (int i = 2; i <= n; i++) {
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i - 1];
}
return min(dp[n], dp[n - 1]);
}
int main() {
int n;
cin >> n;
vector<int> cost(n);
for (int i = 0; i < n; i++) {
cin >> cost[i];
}
cout << compute(cost) << endl;
return 0;
}
题目解析
判断题
- 当输入的 cost 数组为 {10, 15, 20} 时,程序的输出为 15。(正确)
解析:模拟一遍过程:
步骤 | dp值计算过程 | dp值 | 当前最小成本 |
---|---|---|---|
0 | - | dp[0] = 0 | - |
1 | dp[1] = cost[0] | dp[1] = 10 | - |
2 | min(dp[0], dp[1]) + 15 = 0 + 15 | dp[2] = 15 | - |
3 | min(dp[1], dp[2]) + 20 = 10 + 20 | dp[3] = 30 | min(15, 30) = 15 |
- 如果将 dp[i-1] 改为 dp[i-3],程序可能会产生编译错误。(错误)
解析:这样改语法仍然合法,不会产生编译错误,但可能会因为数组越界而导致运行时错误。 - 程序总是输出 cost 数组中最小的元素。(错误)
解析:很显然,输出不是输出最小的元素。
单选题
- 当输入的 cost 数组为 {1,100,1,1,1,100,1,1,100,1} 时,程序的输出为(A)。
A. 6
B. 7
C. 8
D. 9
解析:模拟一遍过程:
步骤 | dp值计算过程 | dp值 | 当前最小成本 |
---|---|---|---|
0 | - | dp[0] = 0 | - |
1 | dp[1] = cost[0] | dp[1] = 1 | - |
2 | min(dp[0], dp[1]) + 100 = 0 + 100 | dp[2] = 100 | - |
3 | min(dp[1], dp[2]) + 1 = 1 + 1 | dp[3] = 2 | - |
4 | min(dp[2], dp[3]) + 1 = 2 + 1 | dp[4] = 3 | - |
5 | min(dp[3], dp[4]) + 1 = 2 + 1 | dp[5] = 3 | - |
6 | min(dp[4], dp[5]) + 100 = 3 + 100 | dp[6] = 103 | - |
7 | min(dp[5], dp[6]) + 1 = 3 + 1 | dp[7] = 4 | - |
8 | min(dp[6], dp[7]) + 1 = 4 + 1 | dp[8] = 5 | - |
9 | min(dp[7], dp[8]) + 100 = 4 + 100 | dp[9] = 104 | - |
10 | min(dp[8], dp[9]) + 1 = 5 + 1 | dp[10] = 6 | min(104, 6) = 6 |
- 如果输入的 cost 数组为 {10,15,30,5,5,10,20},程序的输出为(B)。
A. 25
B. 30
C. 35
D. 40
解析:模拟一遍过程:
步骤 | dp值计算过程 | dp值 | 当前最小成本 |
---|---|---|---|
0 | - | dp[0] = 0 | - |
1 | dp[1] = cost[0] | 10 | - |
2 | min(0, 10) + 15 | 15 | - |
3 | min(10, 15) + 30 | 40 | - |
4 | min(15, 40) + 5 | 20 | - |
5 | min(40, 20) + 5 | 25 | - |
6 | min(20, 25) + 10 | 30 | - |
7 | min(25, 30) + 20 | 45 | min(30, 45) = 30 |
- 若将代码中的 min(dp[i - 1], dp[i - 2]) + cost[ i - 1] 修改为 dp[i - 1] + cost[i - 2],输入 cost 数组为 {5,10,15} 时,程序的输出为(A)。
A. 10
B. 15
C. 20
D. 25
解析:
步骤 | dp值计算过程 | dp值 | 当前最小成本 |
---|---|---|---|
0 | - | dp[0] = 0 | - |
1 | dp[1] = cost[0] | dp[1] = 5 | - |
2 | dp[1] + cost[0] = 5 + 5 | dp[2] = 10 | - |
3 | dp[2] + cost[1] = 10 + 10 | dp[3] = 20 | min(20, 10) = 10 |
阅读程序第三题解析
#include <iostream>
#include <cmath>
using namespace std;
int customFunction(int a, int b) {
if (b == 0) {
return a;
}
return a + customFunction(a, b - 1);
}
int main() {
int x, y;
cin >> x >> y;
int result = customFunction(x, y);
cout << pow(result, 2) << endl;
return 0;
}
题目解析
判断题
- 当输入为 2 3 时,customFunction(2, 3) 的返回值为 64。(错误)
解析:customFunction(2, 3)
= 2 + customFunction(2, 2)
= 2 + 2 + customFunction(2, 1)
= 2 + 2 + 2 + customFunction(2, 0)
= 2 + 2 + 2 + 2
= 8 - 当 b 为负数时,customFunction(a, b) 会陷入无限递归。(正确/错误)
解析:理论上 customFunction(a, b) 不会无限递归,但会进行非常多次的递归调用(可能导致栈溢出)。
从实际运行的角度来看,由于栈空间有限,b 为负数时几乎肯定会因为栈溢出而导致程序崩溃,可以认为是“无限递归”。
题目描述不准确,无意义。 - 当 b 的值越大,程序的运行时间越长。(正确/错误)
**解析:正常情况下,b 的值越大,递归调用的次数越多(b 次递归),因此运行时间越长。
如果 b 为负数,如前面所述,递归次数会非常多(从负数到 INT_MIN 再到 INT_MAX 再到 0),可能比 b 为正数时更多。
题目描述不准确,无意义。
**
单选题
- 当输入为 5 4 时,customFunction(5, 4) 的返回值为(B)。
A. 5
B. 25
C. 250
D. 625
解析:customFunction(5, 4)
= 5 + customFunction(5, 3)
= 5 + 5 + customFunction(5, 2)
= 5 + 5 + 5 + customFunction(5, 1)
= 5 + 5 + 5 + 5 + customFunction(5, 0)
= 25 - 如果输入 x = 3 和 y = 3,则程序的最终输出为(C)。
A. 27
B. 81
C. 144
D. 256
解析:customFunction(3, 3)
= 3 + 3 + 3 + 3
= 12
ans = 122 = 144 - 若将 customFunction 函数改为 return a + customFunction(a-1, b-1);,并输入 3 3,则程序的最终输出为(D)。
A. 9
B. 16
C. 25
D. 36
解析:customFunction(3, 3)
= 3 + customFunction(2, 2)
= 3 + 2 + customFunction(1, 1)
= 3 + 2 + 1 + customFunction(0, 0)
= 6
ans = 62 = 36
完善程序第一题解析
(判断平方数) 问题:给定一个正整数 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;
}
大致分析
根据输出的代码——
if (isSquare(n)) {
cout << n << " is a square number" << endl;
} else {
cout << n << " is not a square number" << endl;
}
可以看出isSquare
返回值为true
时是平方数,为false
时不是平方数。
不难看出,isSquare
就是循环遍历1~(?)
的数,然后挨个挨个判断i2是否等于num。
题目解析
- ① 处应填(A)
A. 1
B. 2
C. 3
D. 4
解析:i应该从1开始,否则会忽略完全平方数1。 - ② 处应填(B)
A. (int)floor(sqrt(num)) - 1
B. (int)floor(sqrt(num))
C. floor(sqrt(num / 2)) - 1
D. floor(sqrt(num / 2))
解析:由于sqrt(num)2 == num,所以i应该找到sqrt(num)为止。 - ③ 处应填(D)
A. num = 2 * i
B. num == 2 * i
C. num = i * i
D. num == i * i
解析:此处应该判断i2是否等于num,如果是,就返回true
,所以选D(C是赋值语句)。 - ④ 处应填(A/C)
A. num = 2 * i
B. num == 2 * i
C. true
D. false
解析:此处应该返回true
,而凑巧i>0,赋值语句A的结果非0,所以A也对。答案A/D。 - ⑤ 处应填(D)
A. num = i * i
B. num != i * i
C. true
D. false
解析:因为此处要返回不是完全平方数的结果,所以选D。
完善程序第二题解析
汉诺塔问题) 给定三根柱子,分别标记为 A、B 和 C。初始状态下,柱子 A 上有若干个圆盘,这些圆盘从上到下按从小到大的顺序排列。任务是将这些圆盘全部移到柱子 C 上,且必须保持原有顺序不变。在移动过程中,需要遵守以下规则:
- 只能从一根柱子的顶部取出圆盘,并将其放入另一根柱子的顶部。
- 每次只能移动一个圆盘。
- 小圆盘必须始终在大圆盘之上。
试补全程序。
#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');
}
代码分析
dfs
函数有4个参数,它们及它们的功能分别是:
- i:当前需要移动的圆盘数量。
- src:源柱子。
- tmp:辅助柱子。
- tgt:目标柱子。
递归终止条件:
- 当只有一个圆盘的时候无需继续递归,直接移动。
if (i == ___①___) {
move(___②___);
return;
}
递归过程:
- 把
i - 1
个圆盘从src
移动到tmp
,把tgt
当辅助柱子。
- 把第
i
个圆盘(底部)直接移到tgt。
- 把
i - 1
个圆盘从tmp
移动到tgt
,把src
当辅助柱子。
题目解析
- ① 处应填(B)
A. 0
B. 1
C. 2
D. 3
解析:当盘数为1
时无需递归,直接移动。 - ② 处应填(B)
A. src, tmp
B. src, tgt
C. tmp, tgt
D. tgt, tmp
解析:当盘数为1时,直接从src
移动到tgt
(直达目标)。 - ③ 处应填(B)
A. src, tmp, tgt
B. src, tgt, tmp
C. tgt, tmp, src
D. tgt, src, tmp
解析:借助tgt
把src
上的圆盘移到tmp。 - ④ 处应填(B)
A. src, tmp, tgt
B. tmp, src, tgt
C. src, tgt, tmp
D. tgt, src, tmp
解析:借助src
把圆盘从tmp
移到tgt
。 - ⑤ 处应填(C)
A. 0
B. 1
C. i - 1
D. i
解析:只需移动i - 1
个,因为第i
个已经在上一行移走了。