#162. 2024 CSP-S 满分之路 模拟卷八
2024 CSP-S 满分之路 模拟卷八
单项选择题(共15题,每题2分,共计30分;每题有且仅有一个正确选项)
- 下列设备中,属于OSI七层模型中数据链路层的是( )。 {{ select(1) }}
- 以太网线
- 路由器
- 交换机
- 光猫
- 在NOI Linux终端系统中,下列哪个命令可以将
a.cpp重命名为b.cpp?( ) {{ select(2) }}
mv a.cpp b.cppcp < a.cpp > b.cpprm a.cpp b.cppecho > a.cpp < b.cpp > b.cpp
- 某算法的执行时间由以下递归式定义:$T(n) = 2T(\frac{n}{2}) + O(n^{\frac{1}{c}}) (c > 1)$,该递归式的时间复杂度是( )。 {{ select(3) }}
- 以下对数据结构或算法的表述中不恰当的一项是( )。 {{ select(4) }}
- 栈是一种后进先出的数据结构
- 平衡树可以在时间内完成遍历
- 随机访问长度为n的链表中一个元素的期望复杂度是
- 二叉堆是一棵完全二叉树
- 执行以下C++代码后,z的值是( )。
int z = (unsigned long long)(-5) % 5;
{{ select(5) }}
0123
- 一棵大小为n的树恰好有两个重心的必要不充分条件是( )。 {{ select(6) }}
- 这棵树有奇数个结点
- 这棵树有偶数个结点
- 这棵树存在两个结点,使得删去它们后剩下的所有连通分量的大小不超过
- 这棵树可以完成黑白染色
- 关于的整系数方程的解,下列说法中正确的是( )。 {{ select(7) }}
- 当且仅当时,该方程存在一组整数解
- 该方程要么有无数个整数解,要么无解
- 若为该方程的一组解,则该方程的通解为,,
- 在使用cxgcd算法求解上述问题的过程中,若,则计算时的中间结果需要使用
long long保存
- 有8个结点,每个点度数不超过3的树最多有( )个叶子结点。 {{ select(8) }}
345- 以上答案都不对
- 以下关于算法复杂度的描述,不正确的是( )。 {{ select(9) }}
- 基于比较的排序复杂度可以低于
- 对一个有n个顶点、m条边的带权有向图用Dijkstra算法计算单源最短路时,若使用斐波那契堆进行优化,则复杂度为
- RMQ(区间最值查询)问题的最优在线算法时间复杂度是
- 普通线段树的空间复杂度是
- 定义一个数x是优美的,当且仅当x的二进制表示下0比1多,问0~255中有多少个数是优美的?( ) {{ select(10) }}
6465127128
- 下图合法的拓扑序数量是( )。 {{ select(11) }}
91287
- 定义两个字符串A、B的编辑距离如下:
- 设A和B是两个字符串,编辑距离指使字符串A转换为字符串B所需的最少字符操作次数。这里所说的字符操作共有3种:
- 删除一个字符;
- 插入一个字符;
- 将一个字符改为另一个字符。
字符串
platelets与planets的编辑距离是( )。
- 设A和B是两个字符串,编辑距离指使字符串A转换为字符串B所需的最少字符操作次数。这里所说的字符操作共有3种:

{{ select(12) }}
3456
- 现在用如下代码计算,其中a的下标从0开始,长度为,其时间复杂度为( )。
int Sol(int *a, int n) {
int sum = 0;
for (int o = 1; o < (1 << n); o <<= 1) {
for (int i = 0; i < (1 << n); i += (o << 1)) {
for (int j = 0; j < o; j++) {
for (int k = 0; k < o; k++) {
sum += a[i + j] * a[i + k + o];
}
}
}
}
return sum;
}
{{ select(13) }}
- 学生需要将编号为1,2,3,4,5,...的方块顺次放入盒子中,每次放入方块时,需要保证盒子中其余方块(不包括当前放入的方块)的编号之和为完全平方数。当有5个盒子时,最多可以放置( )个方块。 {{ select(14) }}
8101213
- 甲乙二人各有两枚石头,在一个回合中,一人抛硬币,如果正面朝上,则将一枚石头交给对方,交不出来就输了,如果反面朝上则什么都不做。甲乙二人轮流进行游戏,甲先手,甲获胜的概率是( )。 {{ select(15) }}
阅读程序(程序输入不超过数组或字符串定义的范围;判断题正确填,错误填x;除特殊说明外,判断题每题1.5分,选择题每题3分,共计40分)
(1)
01 #include <bits/stdc++.h>
02 using namespace std;
03 int a[1 << 10], b[1 << 10], c[1 << 10], d[1 << 10], n;
04 int main() {
05 scanf("%d", &n);
06 for (int i = 0; i < (1 << n); i++)
07 scanf("%d", &a[i]), d[i] = a[i];
08 for (int s = 0; s < (1 << n); s++)
09 for (int s2 = 0; s2 < (1 << n); s2++)
10 if ((s & s2) == s2)
11 b[s] += a[s2];
12 for (int s = 0; s < (1 << n); s++) {
13 int s2 = s;
14 while (s2) {
15 c[s] += a[s2], s2 = (s2 - 1) & s;
16 }
17 }
18 for (int i = 0; i < n; i++)
19 for (int s = 0; s < (1 << n); s++)
20 if ((s >> i) & 1)
21 d[s] += d[s ^ (1 << i)];
22 for (int i = 0; i < (1 << n); i++)
23 printf("%d ", b[i]);
24 puts("");
25 for (int i = 0; i < (1 << n); i++)
26 printf("%d ", c[i]);
27 puts("");
28 for (int i = 0; i < (1 << n); i++)
29 printf("%d ", d[i]);
30 puts("");
31 return 0;
32 }
注:输入的n满足,。
■ 判断题 16. 输出中的第2行一定与第1行不同。( ) {{ select(16) }}
- 正确
- 错误
- 输出中的第3行不一定与第1行相同。( ) {{ select(17) }}
- 正确
- 错误
- 把第14行中的
s2改为s2 >= 0,程序不会进入死循环。( ) {{ select(18) }}
- 正确
- 错误
- (2分)把第18行中的
for (int i = 0; i < n; i++)改成for (int i = n - 1; i >= 0; i--)后,程序的输出结果不变。( ) {{ select(19) }}
- 正确
- 错误
■ 选择题
20. 当输入为0 1时,第2行输出结果为( )。
{{ select(20) }}
102-1
- 当输入为
3 1 2 3 4 5 6 7 8时,第2行输出结果为( )。 {{ select(21) }}
1 2 3 4 5 6 7 81 3 4 10 6 11 16 360 2 3 9 5 10 15 350 2 3 9 5 13 15 35
(2)
01 #include <bits/stdc++.h>
02 using namespace std;
03 long long a[10000];
04
05 int main() {
06 int n, m, k;
07 cin >> n >> m >> k;
08 a[0] = 1;
09 while (k--) {
10 long long sum[100] = {};
11 for (int i = 0; i < n; i++)
12 for (int j = 0; j < m; j++)
13 sum[j] = a[i * m + j] += sum[j];
14 long long s = 0;
15 for (int i = 0; i < m; i++)
16 swap(sum[i], s), s += sum[i];
17 for (int i = 0; i < n; i++)
18 for (int j = 0; j < m; j++)
19 a[i * m + j] += sum[j];
20 }
21 cout << a[n * m - 1] << endl;
22 }
注:都是正整数,程序运行中不会发生long long溢出。
■ 判断题 22. 当时,一定不会发生数组越界。( ) {{ select(22) }}
- 正确
- 错误
- 删掉第14~19行,输出一定不会增大。( ) {{ select(23) }}
- 正确
- 错误
- (2分)当中任意一个增大而另外两个不变时,输出一定会增大。( ) {{ select(24) }}
- 正确
- 错误
■ 选择题
25. 当输入为1 2 10时,输出为( )。
{{ select(25) }}
110551024
- 当输入为
20 15 10时,记输出为X;当输入为15 20 10时,记输出为Y。那么X和Y的大小关系为( )。 {{ select(26) }}
- 不能确定
- 当输入为
100 100 3时,输出为( )。 {{ select(27) }}
49995000500050005001500150025003
(3)
01 #include <bits/stdc++.h>
02 using namespace std;
03
04 int foobar(vector<int> A, int k) {
05 if (A.size() < 5) {
06 sort(A.begin(), A.end());
07 return A[k];
08 }
09 vector<int> B;
10 for (int i = 0; i + 4 < A.size(); i += 5) {
11 sort(A.begin() + i, A.begin() + i + 5);
12 B.push_back(A[i + 2]);
13 }
14 int value = foobar(B, B.size() / 2);
15 vector<int> left, right;
16 for (int v : A) {
17 if (v < value) left.push_back(v);
18 if (v > value) right.push_back(v);
19 }
20 if (k < left.size()) return foobar(left, k);
21 if (k < A.size() - right.size()) return value;
22 return foobar(right, k - (A.size() - right.size()));
23 }
24
25 int main() {
26 ios::sync_with_stdio(false), cin.tie(nullptr);
27 int n, k;
28 cin >> n >> k;
29 vector<int> A(n);
30 for (int i = 0; i < n; i++) cin >> A[i];
31 cout << foobar(A, k) << endl;
32 }
注:假设。
■ 判断题 28. 该程序的功能是求第k小的元素。( ) {{ select(28) }}
- 正确
- 错误
- 该程序的最坏时间复杂度优于快速排序。( ) {{ select(29) }}
- 正确
- 错误
- 把第21行的
k < A.size() - right.size()改为k >= 0,效果不变。( ) {{ select(30) }}
- 正确
- 错误
■ 选择题
- 当输入为
6 3 3 1 5 5 2 2时,输出为( )。 {{ select(31) }}
1235
- 最坏情况下,该程序的时间复杂度为( )。 {{ select(32) }}
- 假设删掉第11行,最坏情况下该程序的时间复杂度为()。 {{ select(33) }}
- 以上都不对
完善程序(单选题,每小题3分,共计30分)
(1) 最长超集子序列
给定一个的排列,定义超集子序列需要满足,即,求出最长超集子序列的长度。
提示:设表示以结尾的最长超集子序列的长度,转移为(),直接转移复杂度为,无法通过。动态维护辅助数组表示,其中要满足在二进制表示下的高位为、低位为的子集,用公式表达为: [g_{A,B} = \max{dp_j} \left(C \subseteq B, P_j = A \times 2^{\left\lfloor\frac{n}{2}\right\rfloor} + C\right)]
试补全程序。
01 #include <bits/stdc++.h>
02 using namespace std;
03 int n, P[1 << 20], dp[1 << 20], g[1 << 10][1 << 10];
04
05 void foobar(int &a, int b) {
06 if (①) a = b;
07 }
08
09 int main() {
10 ios::sync_with_stdio(false), cin.tie(nullptr);
11 cin >> n;
12 for (int i = 0; i < 1 << n; i++) cin >> P[i];
13 for (int i = 0; i < 1 << n; i++) {
14 int A = P[i] >> n / 2, B = P[i] & (②);
15 for (int subset = A;; subset = (subset - 1) & A) {
16 foobar(dp[i], g[subset][B] + 1);
17 if (subset == 0) break;
18 }
19 for (int superset = B;; ③) {
20 foobar(④, dp[i]);
21 if (superset == ⑤) break;
22 }
23 }
24 int ans = 0;
25 for (int i = 0; i < 1 << n; i++) foobar(ans, dp[i]);
26 cout << ans << endl;
27 }
- ①处应填( )。 {{ select(34) }}
a < ba > ba = ba \neq b
- ②处应填( )。 {{ select(35) }}
1 << n(1 << n) - 1(1 << n) - (1 << n / 2)(1 << n / 2) - 1
- ③处应填( )。 {{ select(36) }}
superset = Bsuperset |= Bsuperset = (superset - 1) & Bsuperset |= B
- ④处应填( )。 {{ select(37) }}
g[A][superset]g[B][superset]g[superset][A]g[superset][B]
- ⑤处应填( )。 {{ select(38) }}
0(1 << n) - 1(1 << n) - (1 << n / 2)(1 << n / 2) - 1
(2) 有限分数计数
给定正整数,求出有序整数对的个数,满足,且可以表示为十进制有限小数。
提示:可以表示为十进制有限小数的条件是,先把中所有2和5的因子去掉得到,必须是整数。我们可以枚举,快速算出有多少对合法。
试补全程序。
01 #include <bits/stdc++.h>
02 using namespace std;
03
04 int main() {
05 int n;
06 cin >> n;
07 vector<int> num;
08 for (int A = 1; A <= n; A *= 2)
09 for (int B = 1; A * B <= n; ①)
10 num.push_back(A * B);
11 ②;
12 long long ans = 0;
13 for (int i = 1; i <= n; i++)
14 if (③) {
15 while (!num.empty() && num.back() > ④) num.pop_back();
16 ans += ⑤;
17 }
18 cout << ans << endl;
19 }
- ①处应填( )。 {{ select(39) }}
B++B *= 2B *= 5B *= 10
- ②处应填( )。 {{ select(40) }}
sort(num.begin(), num.end(), less<int>())sort(num.begin(), num.end(), greater<int>())sort(num.rbegin(), num.rend())sort(num.begin(), num.rend(), less<int>())
- ③处应填( )。 {{ select(41) }}
i \% 2 == 0 && i \% 5 == 0i \% 2 == 0 || i \% 5 == 0i \% 2 != 0 && i \% 5 != 0i \% 2 != 0 || i \% 5 != 0
- ④处应填( )。 {{ select(42) }}
inn / in - 1LL * i * i
- ⑤处应填( )。 {{ select(43) }}
num.size()1LL * num.size() * i1LL * num.size() * (n / i)n / i * num.size()