#156. 2024 CSP-S 满分之路 模拟卷二
2024 CSP-S 满分之路 模拟卷二
单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)
- 在NOI Linux系统终端中,以下哪个命令可以用来创建一个新的空白文档?( ) {{ select(1) }}
mkdircp -amvtouch
- 以下关于数据结构的表述中不恰当的一项是( )。 {{ select(2) }}
- 栈是一种后进先出的数据结构
- 非连通有向图的边数一定小于顶点数
- 队列是一种先进先出的数据结构
- 哈希表是一种通过哈希函数将关键字映射到存储位置的数据结构
- 对于4个结点的简单有向图,最少( )条边可以形成一个覆盖所有结点的环。 {{ select(3) }}
2345
- 对于给定的正整数a和n(n为2的正整数次幂),下面求(a^{n})值的方法的最准确描述是( )。
Long long fun(int a, int n)
{
Long Long ret = 1;
if (n <= 1)
return pow(a, n);
else
{
ret = fun(a, n / 2);
return ret * ret;
}
}
{{ select(4) }}
- 倍增
- 二分
- 折半
- 迭代
- 约定杨辉三角形第0行只有1个元素是1,第1行有2个元素是1,则第5行的所有元素之和是( )。 {{ select(5) }}
8163264
- 下列哪个问题不能用贪心法精确求解?( ) {{ select(6) }}
- 哈夫曼编码
- 多重背包
- 打水问题
- 最小生成树
- 对于具有n个元素的二叉排序树(又名二分查找树),进行后序遍历的时间复杂度是( )。 {{ select(7) }}
- (O(log n))
- (O(n))
- (O\left(n^{2}\right))
- (O(n log n))
- 考虑对n个数进行排序,以下方法中最坏时间复杂度最优的排序方法是( )。 {{ select(8) }}
- 选择排序
- 快速排序
- 堆排序
- 插入排序
- 下面有向图中的数字表示顶点序号,则从1号顶点出发的BFS遍历输出的顶点序列可能是( )。 {{ select(9) }}

1 4 3 21 4 2 31 3 2 41 2 4 3
- 给定地址区间为0~10的哈希表,哈希函数为
h(x)=x % 11,采用线性探查的冲突解决策略(若出现冲突情况,会往后探查第一个空的地址存储;若地址10冲突了,则从地址0重新开始探查)。哈希表初始为空表,依次存储(60,34,62,8,2,57,78)后,78存储在哈希表的哪个地址中?( ) {{ select(10) }}
1234
- STL中的容器可以分为顺序容器和关联容器。以下哪个不属于顺序容器?( ) {{ select(11) }}
multisetvectorlistdeque
- 二分图是指能将顶点划分成两个部分,且每一部分内的顶点间没有边相连的简单无向图。含有24个顶点的二分图(两部分的顶点和之差不超过6)至少有( )条边。 {{ select(12) }}
144128135140
- 令二叉树根结点的高度为0,则一棵含有2024个结点的二叉树的高度可能是( )。 {{ select(13) }}
2024202398
- 设全集(I={1,2,3,4,5}),选择集合I的两个非空子集A和B,要使B中最小的数大于A中最大的数,则不同的选择方法有( )种。 {{ select(14) }}
50494847
- 设全集(I={1,2,3,4,5,6,7,8}),集合(B \cup A={1,2,3,4,5,6}),(C \cap A={3,4,5}),(\sim B \cap A={1,4}),那么集合(C \cap B \cap A)为( )。 {{ select(15) }}
{3,5}{4,5}{3,4,5}{4,6}
阅读程序(程序输入不超过数组或字符串定义的范围;判断题正确填,错误填x;除特殊说明外,判断题每题1.5分,选择题每题3分,共计40分)
(1)
01 #include <bits/stdc++.h>
02 using namespace std;
03 typedef pair <int, int> PII;
04 const int N = 1007;
05 int n, m, ans;
06 char g[N][N];
07 bool st[N][N];
08 void bfs(int x, int y) {
09 queue<PII> q;
10 q.push({x, y});
11 st[x][y] = true;
12 while (q.size()) {
13 PII t = q.front();
14 q.pop();
15 for (int i = t.first - 1; i <= t.first + 1; ++i)
16 for (int j = t.second - 1; j <= t.second + 1; ++j) {
17 if (i == t.first && j == t.second)
18 continue;
19 if (i < 1 || i > n || j < 1 || j > m)
20 continue;
21 if (g[i][j] != 'W' || st[i][j])
22 continue;
23 q.push({i, j});
24 st[i][j] = true;
25 }
26 }
27 }
28 int main()
29 {
30 cin >> n >> m;
31 for (int i = 1; i <= n; ++i)
32 scanf("%s", g[i] + 1);
33 for (int i = 1; i <= n; ++i)
34 for (int j = 1; j <= m; ++j)
35 if (g[i][j] == 'W' && !st[i][j]) {
36 bfs(i, j);
37 ++ans;
38 }
39 printf("%d\n", ans);
40 return 0;
41 }
■ 判断题
16. 若将第30行改为cin>>m>>n;,程序的输出不变。( )
{{ select(16) }}
- 正确
- 错误
- 该问题也可以用DFS解决。( ) {{ select(17) }}
- 正确
- 错误
- 当输入为 4 5 WSWWSS WWWSSS SSWSWS SSSSWS 时,程序会崩溃。( ) {{ select(18) }}
- 正确
- 错误
- 从程序中可以看出题目允许的拓展方向有4个。( ) {{ select(19) }}
- 正确
- 错误
■ 选择题 20. 对于输入 4 5 WSWWS WWWSS SSWSW SSSSW 程序的输出是( )。 {{ select(20) }}
1234
- 本程序的时间复杂度是( )。 {{ select(21) }}
- (O(n))
- (O\left(n^{2} m^{2}\right))
- (O\left(n^{2} m\right))
- (O(n m))
(2)
01 #include <bits/stdc++.h>
02 using namespace std;
03
04 typedef struct {
05 double x;
06 double y;
07 }Point;
08
09 Point point_init(double x, double y) {
10 Point p;
11 p.x = x;
12 p.y = y;
13 return p;
14 }
15
16 Point point_sub(Point a, Point b) {
17 Point p;
18 p.x = a.x - b.x;
19 p.y = a.y - b.y;
20 return p;
21 }
22
23 double cross(Point a, Point b) {
24 return a.x * b.y - a.y * b.x;
25 }
26
27 double polygonArea(const vector<Point> v) {
28 double area = cross(v.back(), v.front());
29 for (size_t i = 0; i < v.size() - 1; ++i) {
30 area += cross(v[i], v[i + 1]);
31 }
32 return area;
33 }
34
35 void solve(int n) {
36 vector<Point> pts(n);
37 for (int i = 0; i < n; ++i) {
38 double a, b;
39 cin >> a >> b;
40 pts[i] = point_init(a, b);
41 }
42 double area = polygonArea(pts) / 2;
43 cout << fixed << setprecision(1) << fabs(area) << endl;
44 }
45
46 int main() {
47 while (true) {
48 int n;
49 cin >> n;
50 if (n == 0) break;
51 solve(n);
52 }
53 return 0;
54 }
■ 判断题
22. 将第42行改为double area = polygonArea(pts) >> 1;,程序正常运行。( )
{{ select(22) }}
- 正确
- 错误
- 无论点是按逆时针方向还是按顺时针方向给出,程序都可以计算出正确的结果。( ) {{ select(23) }}
- 正确
- 错误
- 程序可以处理凹多边形而不需要任何修改。( ) {{ select(24) }}
- 正确
- 错误
polygonArea的返回值始终为正。( ) {{ select(25) }}
- 正确
- 错误
■ 选择题
26. cross函数的计算结果用于表示( )。
{{ select(26) }}
- 两个点的欧几里得距离
- 连接两点的直线的斜率
- 两个向量的点积
- 两个向量的叉积
- 对于输入 3 1 1 0 0 1 0 程序输出( )。 {{ select(27) }}
1.00.50.00.6
(3)
01 #include <bits/stdc++.h>
02 using namespace std;
03
04 class BIT {
05 public:
06 vector<int> bit;
07 int size;
08 BIT(int n) : size(n), bit(n + 1, 0) {}
09 void update(int x, int delta) {
10 ++x;
11 while (x <= size) {
12 bit[x] += delta;
13 x += x & -x;
14 }
15 }
16 int query(int x) const {
17 ++x;
18 int sum = 0;
19 while (x > 0) {
20 sum += bit[x];
21 x -= x & -x;
22 }
23 return sum;
24 }
25 };
26
27 int main() {
28 int n, q;
29 cin >> n >> q;
30 vector<int> arr(n);
31 vector<pair<int, int>> queries[q];
32 vector<int> solution(q);
33 for (int i = 0; i < n; ++i) {
34 cin >> arr[i];
35 }
36 for (int i = 0; i < q; ++i) {
37 int a, b;
38 cin >> a >> b;
39 a--, b--;
40 queries[a].emplace_back(b, i);
41 }
42 BIT bit(n);
43 map<int, int> last_index;
44 for (int i = n - 1; i >= 0; --i) {
45 int val = arr[i];
46 if (last_index.find(val) != last_index.end()) {
47 bit.update(last_index[val], -1);
48 }
49 last_index[val] = i;
50 bit.update(i, 1);
51
52 for (const auto& query : queries[i]) {
53 solution[query.second] = bit.query(query.first);
54 }
55 }
56 for (int ans : solution) {
57 cout << ans << ' ';
58 }
59 return 0;
60 }
■ 判断题 28. 程序支持在线查询。( ) {{ select(28) }}
- 正确
- 错误
- 将第13行改为
x += x & (~x + 1);,程序功能不变。( ) {{ select(29) }}
- 正确
- 错误
■ 选择题
30. BIT类中的query函数的返回值是( )。
{{ select(30) }}
- 指定索引的值
- 自根开始到指定索引的所有值的乘积
- 指定索引之前所有值的累加和
- 自根开始到指定索引的所有值的最大值
- 程序的时间复杂度为( )。 {{ select(31) }}
- (O(n))
- (O(n log n))
- (O\left(n^{2} log n\right))
- (O(log n))
- 如果输入的arr数组的元素大小互不相同,则
last_index.size()的值是( )。 {{ select(32) }}
01nq
- (4分)如果输入为 5 3 3 2 3 1 2 1 3 2 4 1 5 则输出将是( )。 {{ select(33) }}
2 3 33 2 43 2 50 1 0
完善程序(单选题,每小题3分,共计30分)
(1) 定义*数字,对于一个没有前导0的数,数字d恰好出现在这个数的所有偶数位置。现在给定(m, d, a, b),询问([a, b])范围内是m倍数的x数字的数量,答案对1e9+7取模。
01 #include <bits/stdc++.h>
02 using namespace std;
03
04 const int M = 2005;
05 const int mod = 1e9 + 7;
06 int dp[M][M][2];
07 int m, d;
08
09 int dfs(int i, int sum, int small_taken, string s) {
10 if (①) return sum == 0;
11 int ans = dp[i][sum][small_taken];
12 if (ans != -1) return ans;
13 ans = 0;
14 int digit = s[i] - '0';
15 int low = 0, high = digit;
16 if (small_taken) high = 9;
17 for (int j = low; j <= high; ++j) {
18 if (i % 2 == 1 && j != d) continue;
19 if (i % 2 == 0 && j == d) continue;
20 int new_small = ②;
21 int new_sum = ③;
22 ans += dfs(i + 1, new_sum, new_small, s);
23 ans %= mod;
24 }
25 return dp[i][sum][small_taken] = ans;
26 }
27
28 int main() {
29 string a, b;
30 cin >> m >> d >> a >> b;
31 int is_a_magic = 1;
32 int res = 0;
33 for (int i = 0; i < a.size(); ++i) {
34 int dig = a[i] - '0';
35 if ((i % 2 == 1 && dig != d)) is_a_magic = 0;
36 if (④) is_a_magic = 0;
37 res = (res * 10 + dig) % m;
38 }
39 if (res) is_a_magic = 0;
40 memset(dp, -1, sizeof dp);
41 int sum_a = dfs(0, 0, 0, a);
42 memset(dp, -1, sizeof dp);
43 int sum_b = dfs(0, 0, 0, b);
44 cout << ⑤ << endl;
45 return 0;
46 }
- ①处应填( )。 {{ select(34) }}
i >= s.size()i > s.size()i >= sumi > sum
- ②处应填( )。 {{ select(35) }}
j != d || j < highsmall_taken && j < highj == d || j < highsmall_taken || j < high
- ③处应填( )。 {{ select(36) }}
(sum + digit) % m(sum * 10 + j) % m(sum + high) % m(sum * 10 + high) % m
- ④处应填( )。 {{ select(37) }}
i % 2 == 1 && dig == ddig != d || is_a_magici % 2 == 0 && dig != ddig != d && !is_a_magic
- ⑤处应填( )。 {{ select(38) }}
(sum_b - sum_a + mod) % mod(sum_b - is_a_magic) % mod(sum_b - sum_a - is_a_magic + mod) % mod(sum_b + sum_a + is_a_magic) % mod
(2) 给定n个人和m条信息,每条信息描述了若干人的站队要求,比如信息2、5、1,那么站队时2号应该在5号前,5号应该在1号前,这些信息是按照优先级排列的,所以现在希望你能找到一个站队序列满足前x条信息,使得这个x尽可能大。对于这个最大的x,你需要找到字典序最小的答案。
01 #include <bits/stdc++.h>
02 #define LL long long
03 #define PII pair<int, int>
04 using namespace std;
05
06 vector<int> ret;
07 vector<vector<int>> order;
08 int n, m;
09
10 struct TopoSort {
11 int N;
12 vector<int> in, res;
13 vector<vector<int>> adj;
14 void init(int _N) {
15 N = _N;
16 in.resize(N);
17 adj.resize(N);
18 }
19 void addedge(int x, int y) { adj[x].push_back(y), ①; }
20 bool sort() {
21 ②;
22 for (int i = 1; i < N; i++)
23 if (③) todo.push(i);
24 while (todo.size()) {
25 int x = todo.top(); todo.pop();
26 res.push_back(x);
27 for (const int& i : adj[x])
28 if (!(--in[i])) todo.push(i);
29 }
30 return res.size() == N - 1;
31 }
32 };
33
34 bool check(int x) {
35 TopoSort g;
36 g.init(n + 1);
37 for (int i = 0; i < x; i++) {
38 for (int j = 0; j < order[i].size() - 1; j++) {
39 g.addedge(order[i][j], order[i][j + 1]);
40 }
41 }
42 bool ans = g.sort();
43 if (ans)
44 ④;
45 return ans;
46 }
47
48 int main() {
49 cin >> n >> m;
50 order.resize(m);
51 for (int i = 0; i < m; i++) {
52 int k; cin >> k;
53 vector<int> v(k);
54 for (int j = 0; j < k; j++) cin >> v[j];
55 order[i] = v;
56 }
57 int l = 0, r = m;
58 while (l < r) {
59 int mid = ⑤;
60 if (check(mid))
61 l = mid;
62 else
63 r = mid - 1;
64 }
65 check(l);
66 for (int i = 0; i < n; i++) {
67 cout << ret[i] << " ";
68 }
69 return 0;
70 }
- ①处应填( )。 {{ select(39) }}
++in[x]adj[y].push_back(x)++in[y]++res[x]
- ②处应填( )。 {{ select(40) }}
priority_queue<int, vector<int>, greater<int>> todopriority_queue<int, vector<int>, less<int>> todoset<int, less<int>> todoset<int, greater<int>> todo
- ③处应填( )。 {{ select(41) }}
in[i] == iin[i]in[i] != i!in[i]
- ④处应填( )。 {{ select(42) }}
ret[x] = g.res[x]ret = g.res, ret.resize(x)ret.resize(x), ret[x] = g.res[x]ret = g.res
- ⑤处应填( )。 {{ select(43) }}
(l + r) >> 1l + (r - l + 1) >> 1(l + r) / 2l + (r - l + 1) / 2