第 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

相关推荐
blammmp6 分钟前
算法专题四:前缀和
java·开发语言·算法
饕餮争锋13 分钟前
Spring普通配置类 vs 自动配置类-笔记
java·笔记·spring
Aimyon_3627 分钟前
Java复习笔记-基础
java·开发语言·笔记
望未来无悔35 分钟前
系统学习算法:动态规划(斐波那契+路径问题)
java·算法
琢磨先生David41 分钟前
Java 企业级开发设计模式全解析
java·设计模式
天上掉下来个程小白1 小时前
缓存菜品-04.功能测试
java·spring boot·缓存·微信小程序·需求分析·苍穹外卖
明月看潮生1 小时前
青少年编程与数学 02-018 C++数据结构与算法 25课题、图像处理算法
c++·图像处理·算法·青少年编程·编程与数学
我是一只鱼02231 小时前
LeetCode算法题 (反转链表)Day17!!!C/C++
数据结构·c++·算法·leetcode·链表
Xiaohong07161 小时前
工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计 从架构到实操
java·工程管理系统源码·企业工程管理系统源码
不当菜虚困1 小时前
JAVA设计模式——(十一)建造者模式(Builder Pattern)
java·设计模式·建造者模式