第 14 届蓝桥杯 C++ 青少组省赛中 / 高级组真题解析

一、选择题

第 1 题

题目:C++ 中,bool 类型的变量占用字节数为( )。

A. 1

B. 2

C. 3

D. 4

答案:A

解析:

C++ 标准规定,bool类型至少占用 1 字节(1 byte),用于存储true(非 0)或false(0)。尽管逻辑上只需 1 位,但内存分配以字节为最小单位,因此选 A。

考点:C++ 基础数据类型的内存占用。

重点:掌握bool、char、int、double等类型的字节数(如char占 1 字节,int通常占 4 字节)。

教学方案:通过对比表格讲解数据类型,强调bool的特殊性(1 字节而非 1 位),结合内存对齐原则理解

第 2 题

题目:以下关于 C++ 结构体的说法,正确的是( )。

A. 结构体中只能包含成员变量,不能包含成员函数

B. 结构体不能从另一个结构体继承

C. 结构体里面可以包含静态成员变量

D. 结构体里面不能包含构造函数

答案:C

解析:

A 错误:结构体可包含成员函数(与类的区别仅在于默认访问权限为public)。

B 错误:结构体支持继承(语法与类相同,默认public继承)。

C 正确:结构体允许静态成员变量(属于类型本身,而非实例)。

D 错误:结构体可定义构造函数,用于初始化成员。

考点:结构体与类的特性对比。

重点:理解结构体的成员类型(变量、函数、静态成员、构造函数),区分结构体与类的默认访问权限。

教学方案:编写包含成员函数和构造函数的结构体示例,演示继承语法,对比类与结构体的异同。

第 3 题

题目:设只含根结点的二叉树高度为 1,共有 62 个结点的完全二叉树的高度为( )。

A. 4

B. 5

C. 6

D. 7

答案:C

解析:

完全二叉树高度h满足:

前h-1层是满二叉树,结点数为2^(h-1)-1;

第h层至少 1 个结点,最多2^(h-1)个结点。

计算:

当h=5时,前 4 层结点数为2^4-1=15,总结点数最多15+8=23(<62,不满足);

当h=6时,前 5 层结点数为2^5-1=31,总结点数最多31+32=63(≥62,满足)。

故高度为 6,选 C。

考点:完全二叉树的结点数与高度关系。

重点:掌握公式2^(h-1) ≤ 结点数 ≤ 2^h - 1,通过不等式求解高度。

教学方案:画图演示满二叉树与完全二叉树的结构,推导高度计算公式,通过例题强化计算。

第 4 题

题目:以下关于数组的说法,不正确的是( )。

A. 数组中所有元素的类型必须都相同

B. 数组中各元素在内存中是顺序存放的

C. 数组最后一个元素的索引是数组的长度

D. 数组名的第一个字符可以是下划线

答案:C

解析:

A 正确:数组元素类型必须统一(如int arr[5]所有元素均为int)。

B 正确:数组在内存中连续存储,元素地址递增。

C 错误:索引从 0 开始,最后一个元素索引为长度-1(如长度 5 的数组索引 0~4)。

D 正确:数组名是标识符,允许以下划线开头(如_arr)。

考点:数组的基本特性。

重点:强调索引越界风险,区分数组长度与最大索引(长度 - 1)。

教学方案:通过代码示例演示数组定义、访问,故意写出越界代码(如arr[5]对长度 5 的数组),观察错误现象。

第 5 题

题目:执行以下代码,输出结果是( )。

cpp

#include <iostream>

using namespace std;

int f(int k) {

if (k == 1) return 3;

return 2 * f(k - 1) + 1;

}

int main() {

int n = 6;

cout << f(n);

return 0;

}

A. 127

B. 97

C. 63

D. 126

答案:A

解析:

递归函数递推关系:

基例:f(1)=3

递推:f(k)=2*f(k-1)+1

展开计算:

f(2)=2×3+1=7

f(3)=2×7+1=15

f(4)=2×15+1=31

f(5)=2×31+1=63

f(6)=2×63+1=127

考点:递归函数的递推计算。

重点:理解递归终止条件与递推公式,可转化为等比数列(通项公式:f(k)=2^(k+1)-1)。

教学方案:用递归展开法逐步计算,引入数学归纳法推导通项公式,避免深层递归导致栈溢出。

二、编程题

第 6 题:特殊运算符

题目描述:

定义运算符 ">>>N" 为提取 N 的前两位数字(如 257→25,182→18),计算 N - (>>>N)。

输入:三位数 N(100<N<1000)。

输出:N 减去前两位的结果。

样例输入:257 → 输出 232(257-25=232)。

答案代码:

cpp

#include <iostream>

using namespace std;

int main() {

int n;

cin >> n;

int first_two = n / 10; // 提取前两位(如257/10=25)

cout << n - first_two << endl;

return 0;

}

解析:

三位数的前两位可通过整数除法n//10得到(如 933//10=93),直接计算差值即可。

考点:数字处理(整数除法提取高位)。

重点:掌握//和%的用法,明确三位数的结构(百位 ×100 + 十位 ×10 + 个位)。

教学方案:通过分解数字的各位(百位、十位、个位)演示n//100、n//10%10、n%10,强调整数除法的应用。

第 7 题:四叶玫瑰数

题目描述:

找出四位数中各位数字的四次方之和等于自身的数(如 1634=1⁴+6⁴+3⁴+4⁴),输出 N~M 范围内的数。

输入:N 和 M(1≤N≤M≤1e6)。

输出:按从小到大顺序的四叶玫瑰数。

样例输入:1234 2345 → 输出 1634。

答案思路:

仅枚举四位数(1000≤num≤9999),减少计算量;

分解各位数字:千位a=num/1000,百位b=num/100%10,十位c=num/10%10,个位d=num%10;

计算四次方和,若等于原数则输出。

代码框架:

cpp

#include <iostream>

using namespace std;

bool is_rose(int num) {

int a = num / 1000, b = num / 100 % 10, c = num / 10 % 10, d = num % 10;

return a*a*a*a + b*b*b*b + c*c*c*c + d*d*d*d == num;

}

int main() {

int n, m;

cin >> n >> m;

for (int i = max(n, 1000); i <= min(m, 9999); i++) {

if (is_rose(i)) cout << i << " ";

}

return 0;

}

考点:枚举算法与数字分解。

重点:限定枚举范围(仅四位数),优化循环条件,避免无效计算(如处理 N<1000 或 M>9999 的情况)。

教学方案:讲解 "四叶玫瑰数" 的数学定义,演示数字分解方法,强调提前过滤非四位数以提高效率。

第 8 题:质因数的个数

题目描述:

统计 N~M 之间每个数的质因数个数(重复质因数算多个,如 8=2×2×2,个数为 3),求最大值。

输入:N 和 M(1≤N≤M≤1e7)。

输出:最大质因数个数。

样例输入:6 10 → 输出 3(8 的质因数个数为 3)。

答案思路:

对每个数num进行质因数分解:从 2 到√num 试除,统计每个质因数的次数;

若试除后num>1,说明剩余部分是质数,次数加 1;

遍历 N~M,记录最大次数。

代码核心:

cpp

int count_prime_factors(int num) {

int count = 0;

for (int i = 2; i * i <= num; i++) {

while (num % i == 0) { // 统计i的次数

count++;

num /= i;

}

}

if (num > 1) count++; // 处理剩余质数(如7、13等)

return count;

}

考点:质因数分解与贪心统计。

重点:试除法分解质因数,区分质因数的 "种类" 与 "个数"(本题统计个数,包括重复)。

教学方案:通过示例(如 12=2²×3¹,个数 2+1=3)讲解质因数个数的定义,演示试除过程,强调从小到大试除以确保质因数。

第 9 题:最大的矩形纸片

题目描述:

在直方图中找最大矩形面积(高度数组 [3,2,1,4,5,2] 的最大面积为 8)。

输入:N(列数)和高度数组。

输出:最大矩形面积。

答案思路:

使用单调栈算法:

维护一个单调递增栈,存储索引,对应高度递增;

遍历每个高度,找到左右两边第一个比它小的位置,计算宽度right - left - 1,面积 = 高度 × 宽度;

处理边界条件(数组末尾加 0,确保栈中元素全部弹出)。

代码框架:

cpp

#include <iostream>

#include <stack>

using namespace std;

long long max_area(int n, int* heights) {

stack<int> st;

long long res = 0;

for (int i = 0; i <= n; i++) { // 末尾加0,处理所有元素

while (!st.empty() && (i == n || heights[st.top()] >= heights[i])) {

int h = heights[st.top()]; st.pop();

int w = st.empty() ? i : i - st.top() - 1;

res = max(res, (long long)h * w);

}

st.push(i);

}

return res;

}

考点:直方图最大矩形面积(单调栈算法)。

重点:理解单调栈的作用(快速找到左右边界),处理数据类型溢出(使用long long)。

教学方案:通过直方图画图演示单调栈的工作流程,解释每个步骤的意义,对比暴力法与单调栈的时间复杂度(O (n) vs O (n²))。

第 10 题:数字游戏

题目描述:

交替调整最小数到第二小、最大数到第二大,直到不同数少于 3 个,输出调整次数、最终最小和最大值。

输入:数组。

输出:次数、最终最小值、最大值。

样例输入:1 3 4 2 → 调整 2 次,结果 2 2 3。

答案思路:

每次操作后排序数组,统计不同数的数量;

第奇数次操作:将所有最小数改为第二小数;

第偶数次操作:将所有最大数改为第二大数;

直到不同数≤2 时终止。

代码核心:

cpp

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

int main() {

int n;

vector<int> nums;

cin >> n >> nums;

int count = 0;

bool is_min_turn = true; // 第一次调整最小数

while (true) {

sort(nums.begin(), nums.end());

// 统计不同数

int unique = 1;

for (int i = 1; i < n; i++) {

if (nums[i] != nums[i-1]) unique++;

}

if (unique < 3) break;

if (is_min_turn) {

int second_min = nums[1];

for (int i = 0; i < n; i++) {

if (nums[i] == nums[0]) nums[i] = second_min;

}

} else {

int second_max = nums[n-2];

for (int i = 0; i < n; i++) {

if (nums[i] == nums[n-1]) nums[i] = second_max;

}

}

count++;

is_min_turn = !is_min_turn;

}

sort(nums.begin(), nums.end());

cout << count << " " << nums[0] << " " << nums.back() << endl;

return 0;

}

考点:模拟算法与排序。

重点:每次操作后排序,正确识别第二小 / 第二大数,处理边界情况(如所有数相同)。

教学方案:通过示例演示调整过程,强调排序的重要性,讲解如何统计不同数的数量(遍历或使用集合)。

第 11 题:活动人数

题目描述:

树状结构中,选某部门则不能选直接下级,求最大人数(树形动态规划)。

输入:部门数 N,每个部门的上级 F、编号 S、人数 C。

输出:最大人数。

样例输入:6 个部门,输出 11(选部门 1、4、5、6,人数 2+3+2+4=11)。

答案思路:

每个节点有两种状态:

dp[u][1]:选节点 u 时,最大人数(等于 u 的人数 + 所有子节点不选的最大值);

dp[u][0]:不选节点 u 时,最大人数(等于所有子节点选或不选的最大值之和)。

通过深度优先搜索(DFS)递归计算每个节点的状态。

代码框架:

cpp

#include <iostream>

#include <vector>

using namespace std;

struct Node {

int c;

vector<int> children;

};

Node nodes[100001];

int dp[100001][2]; // dp[u][1]选,dp[u][0]不选

void dfs(int u) {

dp[u][1] = nodes[u].c; // 选当前节点,初始化为自身人数

for (int v : nodes[u].children) {

dfs(v);

dp[u][1] += dp[v][0]; // 子节点不能选

dp[u][0] += max(dp[v][0], dp[v][1]); // 子节点可选或不选

}

}

int main() {

int n;

cin >> n;

for (int i = 1; i <= n; i++) {

int f, s, c;

cin >> f >> s >> c;

nodes[s].c = c;

if (f != 0) nodes[f].children.push_back(s); // 构建树结构

}

// 找根节点(上级为0的节点)

int root = 0;

for (int i = 1; i <= n; i++) {

if (nodes[i].children.size() > 0 && (root == 0 || ...)) {

// 实际应遍历找到f=0的s

// 正确方法:记录每个节点的父节点,找父节点为0的节点

}

// 简化:假设根节点是1(需根据输入正确查找)

root = 1; // 实际需遍历所有节点,找到f=0对应的s

}

dfs(root);

cout << max(dp[root][0], dp[root][1]) << endl;

return 0;

}

考点:树形动态规划(树上的选与不选问题)。

重点:树的存储(邻接表),状态转移方程的推导,根节点的确定(上级为 0 的节点)。

教学方案:讲解树的基本概念,演示状态转移方程的推导过程,通过样例分析选与不选的决策对结果的影响,强调递归 DFS 的实现。

详细教学方案

一、选择题模块

数据类型与内存:

对比bool、char、int等类型的字节数,通过代码sizeof(bool)验证。

讲解内存对齐原则,解释为何bool占 1 字节而非 1 位。

结构体与类:

编写包含成员函数、构造函数、静态成员的结构体示例,演示继承语法(struct B : public A)。

对比结构体与类的默认访问权限(public vs private)。

二叉树性质:

画图演示满二叉树与完全二叉树,推导高度计算公式h = floor(log2(n)) + 1。

通过练习题(如结点数 30、63 的高度)强化计算。

数组基础:

演示数组定义、初始化、越界访问,用调试工具观察内存布局。

强调索引从 0 开始,通过错误案例(如访问arr[len])加深印象。

递归函数:

用递归展开法计算第 5 题,引入数学归纳法推导通项公式f(k)=2^(k+1)-1。

讲解递归与迭代的转换,避免栈溢出(如限制递归深度)。

二、编程题模块

数字处理(第 6 题):

讲解整数除法//和取余%的用法,分解三位数的百位、十位、个位。

设计变式题:提取前两位(三位数)、前三位(四位数),计算差值。

枚举算法(第 7 题):

限定枚举范围(四位数),避免无效循环(如 N=500 时从 1000 开始枚举)。

优化数字分解:用数学公式快速获取各位数字,减少计算量。

质因数分解(第 8 题):

演示试除法分解质因数,强调从小到大试除确保质因数(如先除 2,再除 3,直到√num)。

区分质因数的 "个数" 与 "种类"(本题统计个数,包含重复)。

单调栈算法(第 9 题):

通过直方图动画演示单调栈的工作流程,解释每个元素的左右边界如何确定。

对比暴力法(O (n²))与单调栈(O (n))的效率,强调算法优化的重要性。

模拟与排序(第 10 题):

通过示例表格记录每次调整后的数组状态,演示排序的作用(快速找到最小 / 最大值)。

处理边界情况:如所有数相同(直接输出 0 次),或只有两种不同数(无需调整)。

树形动态规划(第 11 题):

讲解树的存储方式(邻接表),如何构建树结构(根据输入的上下级关系)。

推导状态转移方程:选当前节点则子节点不能选,不选则子节点可选或不选,取最大值。

通过样例分析递归过程,强调根节点的正确查找(上级为 0 的节点)。

三、实战训练

选择题:设计 10 道同类题目,涵盖数据类型、结构体、二叉树、数组、递归等考点,限时 5 分钟完成。

编程题:

第 6 题变式:处理四位数,提取前三位,计算差值。

第 8 题优化:预处理质数表,加速质因数分解(适用于大数据范围)。

第 11 题扩展:处理森林(多棵树),求所有树的最大人数之和。

调试技巧:

学会使用断点调试,观察递归过程或循环变量变化。

针对超时问题,分析算法时间复杂度,优化循环条件或选择更高效的算法(如单调栈替代双重循环)。

通过以上教学方案,学生可系统掌握 C++ 基础、算法思维和编程技巧,提升解决竞赛题目的能力。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/m0_46324731/article/details/147691495

相关推荐
.格子衫.1 天前
Spring Boot 原理篇
java·spring boot·后端
多云几多1 天前
Yudao单体项目 springboot Admin安全验证开启
java·spring boot·spring·springbootadmin
Swift社区1 天前
LeetCode 394. 字符串解码(Decode String)
算法·leetcode·职场和发展
tt5555555555551 天前
LeetCode进阶算法题解详解
算法·leetcode·职场和发展
让我们一起加油好吗1 天前
【基础算法】DFS中的剪枝与优化
算法·深度优先·剪枝
Jabes.yang1 天前
Java求职面试实战:从Spring Boot到微服务架构的技术探讨
java·数据库·spring boot·微服务·面试·消息队列·互联网大厂
聪明的笨猪猪1 天前
Java Redis “高可用 — 主从复制”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
Q741_1471 天前
C++ 模拟题 力扣495. 提莫攻击 题解 每日一题
c++·算法·leetcode·模拟
兮动人1 天前
Spring Bean耗时分析工具
java·后端·spring·bean耗时分析工具
MESSIR221 天前
Spring IOC(控制反转)中常用注解
java·spring