STEMA-C++
省202510
省202509
国202506
省202505
本文档使用 MrDoc 发布
-
+
首页
国202506
# STEMA考试 C++试卷(6月)- STEMA国考 ## 一、选择题 ### 第一题 下列选项中,关于 C++ 注释语法正确的是( C)。 A、/* this is a comment B、# this is a comment C、// this is a comment D、*/ this is a comment /* ### 第二题 表达式 (16<sub>8</sub> - 1011<sub>2</sub>) * E<sub>16 </sub>的结果的十进制形式是(D )。 A、42 B、43 C、44 D、45 ### 第三题 假设 int 类型存储的数值范围是 -32768 到 32767,则其占用的内存大小为( B )。 A、1 字节 B、2 字节 C、4 字节 D、8 字节 ### 第四题 一棵包含 2025 个节点的二叉树,根节点高度为 1,该二叉树高度最小为(c)。 A、9 B、10 C、11 D、12 ### 第五题 运行以下程序,输出的结果是( )。 ```cpp int func(int x, int y) { int result = (x & y) | (x >> 2); return result; } int main(){ int a = 0xAF, b = 0xB56; int c = func(a, b); int d = func(b, a); int finalResult = (c ^ d) & (a | (b << 1)); cout << finalResult; return 0; } ``` A、678 B、680 C、682 D、684 要解决这个问题,核心是**逐行拆解位运算**,先明确十六进制与二进制/十进制的转换,再按位运算规则(与&、或|、异或^、移位>>/<<)逐步计算。 #### 步骤1:明确初始值(十六进制转十进制/二进制) - `a = 0xAF`:十六进制转十进制为 \(10×16 + 15 = 175\),二进制为 `1010 1111`。 - `b = 0xB56`:十六进制转十进制为 \(11×16² + 5×16 + 6 = 2902\),二进制为 `1011 0101 0110`。 #### 步骤2:计算 `func(a, b)`(即 `c`) `func(x,y) = (x&y) | (x>>2)`,代入 `x=a=0xAF`,`y=b=0xB56`: 1. **计算 `x&y`(按位与)**: 对齐二进制后逐位与(仅对应位都为1时结果为1): ``` 0xAF: 0000 0000 1010 1111 0xB56: 0000 1011 0101 0110 &结果: 0000 0000 0000 0110 → 十进制6(0x6) ``` 2. **计算 x>>2(右移2位)**: `0xAF >> 2` 即 `1010 1111 >> 2 = 101011`,十进制为43(0x2B)。 3. **计算 `(x&y)|(x>>2)`(按位或)**: `6 | 43 = 0x6 | 0x2B = 0x2F`,十进制为47。 因此 `c = 47`。 #### 步骤3:计算 `func(b, a)`(即 `d`) 代入 `x=b=0xB56`,`y=a=0xAF`: 1. **计算 `x&y`**:按位与满足交换律,结果仍为6(0x6)。 2. **计算 `x>>2`(右移2位)**: `0xB56 >> 2 = 1011 0101 0110 >> 2 = 1011 0101 01`,十进制为725(0x2D5)。 3. **计算 `(x&y)|(x>>2)`**: `6 | 725 = 0x6 | 0x2D5 = 0x2D7`,十进制为727。 因此 `d = 727`。 #### 步骤4:计算 `c^d`(异或) 异或规则:对应位不同为1,相同为0。 - `c=47`(二进制:`0000 0000 0010 1111`) - `d=727`(二进制:`0000 0010 1101 0111`) - 异或结果:`0000 0010 1111 1000` → 十进制760(0x2F8)。 #### 步骤5:计算 `a | (b<<1)`(按位或) 1. **计算 `b<<1`(左移1位)**:`0xB56 << 1 = 0x16AC`,十进制5804。 2. **计算 `a | (b<<1)`**: `0xAF | 0x16AC = 0x16AF`,十进制5807(二进制:`0001 0110 1010 1111`)。 #### 步骤6:计算最终结果 `(c^d) & (a | (b<<1))` 按位与规则:对应位都为1时结果为1。 - `c^d=760`(0x2F8,二进制:`0000 0010 1111 1000`) - `a|(b<<1)=5807`(0x16AF,二进制:`0001 0110 1010 1111`) - 按位与结果:`0000 0010 1010 1000` → 十进制680(0x2A8)。 #### 最终结论 输出结果为 680,对应选项 B。 ## 二、编程题 ### 第一题 **编程实现:**水箱加水 **题目描述:**有一个空水箱,李莉在 T1 时刻向水箱中加入 V1 升水,然后在同一天的 T2 时刻又向水箱中加入 V2 升水(加水消耗的时间忽略不计,水箱的容积足够大)。水箱有一个排水孔,每个小时会排出 1 升水,请问在 T2 时刻加完水后,水箱中一共有多少升水? **输入描述:**一行输入四个整数 T1、V1、T2、V2(0≤T1<T2≤23,1≤V1,V2≤100),分别表示第一次加水的时刻, 第一次加水的体积,第二次加水的时刻,第二次加水的体积,整数之间以一个空格隔开。 **输出描述:**输出一个整数,表示李莉在 T2 时刻加完水后,水箱中水的总体积。 **样例输入:**3 10 10 20 **样例输出:**23 ```cpp #include <iostream> using namespace std; const int N = 100; int a[N][N]; int main() { int t1,v1,t2,v2; cin>>t1>>v1>>t2>>v2; int v = v1-(t2-t1); if(v<0) { v=+v2; } else{ v += +v2; } cout<<v<<endl; return 0; } ``` ### 第二题 **编程实现:**图案描边 **题目描述:**乐乐有一张 n 行 m 列的网格纸,每个格子都是边长为 1 厘米的正方形,网格被绘制了一些图案。乐乐准备沿着图案的边缘进行描边,描边的规则如下:   **输入描述:**第一行输入两个整数 n 和 m(1≤n,m≤100),分别表示网格的行数和列数,整数之间以一个空格隔开;接下来输入 n 行,每行 m 个整数,整数为 1 或 0,1 表示该格子被绘制,0 表示该格子没有被绘制,整数之间以一个空格隔开。 **输出描述**:输出一个整数,表示乐乐一共需要描边的长度。 **样例输入:** 5 3 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 **样例输出:** 12 ```cpp #include <iostream> using namespace std; const int N = 100; int a[N][N]; int main() { int n,m,cnt=0; cin>>n>>m; for(int i = 0;i < n;i ++) { for(int j = 0;j < m;j ++) { cin>>a[i][j]; } } for(int i = 0;i < n;i ++) { for(int j = 0;j < m;j ++) { if(a[i][j]==1) { // 上边 if(i == 0){ cnt++; } else { if(a[i-1][j] == 0) cnt++; } // 下边 if(i == n-1) { cnt ++; } else { if(a[i+1][j] == 0) cnt++; } // 左边 if(j == 0) { cnt++; } else { if(a[i][j-1] == 0) cnt++; } // 右边 if(j == n-1) { cnt ++; } else { if(a[i][j+1] == 0) cnt++; } } } } cout<< cnt <<endl; return 0; } ``` ### 第三题 **编程实现:**美食节 **题目描述:** 在一次美食节上,组委会为市民们准备了 n 种小吃,其中第 i 种小吃有 ai 份。组委会规定: 1)每位市民最多可以领取 x 份小吃; 2)对于同一种小吃,每位市民最多领取 2 份。 请计算最少需要多少位市民,才能把所有的小吃领取完。 **输入描述:** 第一行输入两个整数 n 和 x(1≤n≤105,2≤x≤100),分别表示小吃的种类数以及每位市民最多能领取的小吃份数,整数之间以一个空格隔开; 第二行输入 n 个整数 ai(1≤ai≤109),分别表示每种小吃的份数,整数之间以一个空格隔开。 **输出描述:**输出一个整数,表示最少需要多少位市民,才能把所有的小吃领取完。 **样例输入:** 4 2 1 3 2 5 **样例输出:** 6 ```cpp #include <iostream> #include <cmath> using namespace std; int main() { int n,x,y,s=0; cin>>n>>x; for(int i = 0;i <n;i ++) { cin>>y; s+=y; } int f = ceil(s*1.0/x); cout<<f; return 0; } ``` ### 第四题 **编程实现:**最长的气 **题目描述:**围棋棋盘由 19 条横线和 19 条竖线组成,棋子只能下在交叉点上。与棋子上下左右相邻的空白交叉点属于该棋子的气。 如下图,× 标识的位置为与其相邻的棋子的气,棋子 A 的气数为 2;棋子 B 的气数为 3;棋子 C 和 D的气数均为 3;棋子 E 和 F 的气数均为4   **输入描述:**输入 19 行,每行包含 19 个数字(数字为 0、1 或 2),表示棋盘上棋子的分布情况,0 表示空白,1表示黑棋,2 表示白棋。 **输出描述:**输出一个整数,表示棋盘中气数最多的一块棋的气数。 **样例输入:** 1111111111111111112 0001201200000200101 0210102001000000200 0000000002000000000 0000000000000000000 0000020120021000000 0000010000000000000 0000000000212000212 0000000000120001001 2000000001200002002 1210000002001200000 2000000000000000000 1000100000000020020 0000200000000010012 0121010200000000000 0000020100000000021 0002000002120000010 0001200201200012000 0000002120120121000 **样例输出:**13 ```cpp #include <iostream> #include <queue> #include <set> #include <string> using namespace std; int main() { // 1. 读取19x19棋盘数据 int board[19][19] = {0}; // 棋盘数组 bool visited[19][19] = {false}; // 标记棋子是否已访问 for (int i = 0; i < 19; ++i) { string line; cin >> line; // 读取每行的19个字符 for (int j = 0; j < 19; ++j) { board[i][j] = line[j] - '0'; // 字符转整数 } } // 2. 定义上下左右四个方向偏移量 int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; int max_qi = 0; // 记录最大气数 // 3. 遍历棋盘每个位置 for (int i = 0; i < 19; ++i) { for (int j = 0; j < 19; ++j) { // 仅处理有棋子(1/2)且未访问的位置 if ((board[i][j] == 1 || board[i][j] == 2) && !visited[i][j]) { queue<pair<int, int>> q; // BFS队列,存储棋子坐标 set<pair<int, int>> qi_set; // 存储当前块的气(去重) int color = board[i][j]; // 当前块的棋子颜色 // 初始化BFS q.push({i, j}); visited[i][j] = true; // BFS遍历连通块 while (!q.empty()) { auto [x, y] = q.front(); // C++17及以上支持结构化绑定 q.pop(); // 检查四个方向的相邻点 for (auto [dx, dy] : dirs) { int nx = x + dx; int ny = y + dy; // 确保坐标在棋盘范围内 if (nx >= 0 && nx < 19 && ny >= 0 && ny < 19) { // 情况1:相邻点是同色未访问的棋子 → 加入队列 if (board[nx][ny] == color && !visited[nx][ny]) { visited[nx][ny] = true; q.push({nx, ny}); } // 情况2:相邻点是空白 → 加入气的集合 else if (board[nx][ny] == 0) { qi_set.insert({nx, ny}); } } } } // 更新最大气数 int current_qi = qi_set.size(); if (current_qi > max_qi) { max_qi = current_qi; } } } } // 输出结果 cout << max_qi << endl; return 0; } ``` ```cpp #include <iostream> #include <string> using namespace std; // 棋盘大小 const int SIZE = 19; // 存储棋盘 int board[SIZE][SIZE] = {0}; // 标记棋子是否已访问 bool visited[SIZE][SIZE] = {false}; // 上下左右四个方向 int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 临时存储当前连通块的气(最多361个空白点,足够) int temp_qi[361][2] = {0}; // 当前气的数量(用于temp_qi数组的索引) int qi_count = 0; // 检查坐标(x,y)是否已在temp_qi中(去重) bool isQiExist(int x, int y) { for (int i = 0; i < qi_count; ++i) { if (temp_qi[i][0] == x && temp_qi[i][1] == y) { return true; } } return false; } // 递归DFS遍历连通块,统计气 void dfs(int x, int y, int color) { // 边界条件:坐标越界、已访问、颜色不同 → 直接返回 if (x < 0 || x >= SIZE || y < 0 || y >= SIZE || visited[x][y] || board[x][y] != color) { return; } // 标记当前棋子为已访问 visited[x][y] = true; // 遍历四个方向的相邻点 for (int d = 0; d < 4; ++d) { int nx = x + dirs[d][0]; int ny = y + dirs[d][1]; // 确保相邻点在棋盘内 if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE) { if (board[nx][ny] == color && !visited[nx][ny]) { // 相邻点是同色未访问棋子 → 递归遍历 dfs(nx, ny, color); } else if (board[nx][ny] == 0) { // 相邻点是空白 → 去重后加入气数组 if (!isQiExist(nx, ny)) { temp_qi[qi_count][0] = nx; temp_qi[qi_count][1] = ny; qi_count++; } } } } } int main() { // 1. 读取棋盘数据 for (int i = 0; i < SIZE; ++i) { string line; cin >> line; for (int j = 0; j < SIZE; ++j) { board[i][j] = line[j] - '0'; } } int max_qi = 0; // 记录最大气数 // 2. 遍历棋盘每个位置 for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { // 仅处理有棋子(1/2)且未访问的位置 if ((board[i][j] == 1 || board[i][j] == 2) && !visited[i][j]) { // 重置临时气数组和计数 qi_count = 0; // 递归DFS遍历当前连通块,统计气 dfs(i, j, board[i][j]); // 更新最大气数 if (qi_count > max_qi) { max_qi = qi_count; } } } } // 3. 输出结果 cout << max_qi << endl; return 0; } ``` ### 第五题 **编程实现:**河道清淤计划 **题目描述:**某市水利局需要对一段河床进行清淤。他们将该段河床划分为 2 × n 的网格矩阵,对于每个网格,评估其淤积程度,淤积程度分别用 H(严重淤积) 和 M (中等淤积)标记。同时他们将网格矩阵划分为若干个清淤单元,每个清淤单元由三个位置相邻(上下左右)的网格组成。对于每个清淤单元,如果其中包含两个及以上严重淤积(用 H 标记)的网格,则该单元需要调用重型设备进行清淤,否则,只需要调用常规设备进行清淤,后者花费更小。作为本次清淤工程的管理者,你需要设计一个划分清淤单元的方案,使得需要调用重型设备的清淤单元的数量最少,并输出这个最少数量。 例如:n = 6,2 × 6 的网格区域情况如下:  **输入描述:**第一行输入一个整数 n(3≤n<106,且 n 是 3 的倍数),表示网格矩阵的列数;接下来两行,每行输入一个长度为 n 的字符串,其中仅包含大写字母 'H' 和 'M','H' 表示严重淤积网格,'M' 表示中等淤积网格。 **输出描述:**输出一个整数,表示需要调用重型设备的清淤单元的最少数量。 **样例输入:** 6 MHHHMH MHHMMM **样例输出:** 1 ```cpp #include <iostream> #include <string> #include <algorithm> // 用于min函数 using namespace std; int main() { // 加速输入输出(处理1e6级别的n) ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; string row1, row2; cin >> row1 >> row2; long long total = 0; // 防止极端情况溢出(n=1e6时总最大值约6e5,int也可,long long更安全) // 遍历每个2×3子网格(步长3) for (int s = 0; s < n; s += 3) { // 提取当前子网格的6个格子 char a0 = row1[s], a1 = row1[s+1], a2 = row1[s+2]; char b0 = row2[s], b1 = row2[s+1], b2 = row2[s+2]; // 方式1:两行横向单元(每行3列) int cnt1 = (a0 == 'H') + (a1 == 'H') + (a2 == 'H'); int cnt2 = (b0 == 'H') + (b1 == 'H') + (b2 == 'H'); int sum1 = (cnt1 >= 2) + (cnt2 >= 2); // 布尔值自动转int(true=1,false=0) // 方式2:左上L型 + 右下L型 int cnt3 = (a0 == 'H') + (b0 == 'H') + (a1 == 'H'); int cnt4 = (b1 == 'H') + (a2 == 'H') + (b2 == 'H'); int sum2 = (cnt3 >= 2) + (cnt4 >= 2); // 方式3:左下L型 + 右上L型 int cnt5 = (a0 == 'H') + (b0 == 'H') + (b1 == 'H'); int cnt6 = (a1 == 'H') + (a2 == 'H') + (b2 == 'H'); int sum3 = (cnt5 >= 2) + (cnt6 >= 2); // 取三种方式的最小值(兼容C++11前编译器) int min_sum = min(min(sum1, sum2), sum3); total += min_sum; } cout << total << endl; return 0; } ```
admin
2025年12月5日 10:42
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码