2025年7月6日全国青少年信息素养大赛C++编程初中组复赛真题+答案解析
一、选择题
第1题 C++表达式 (5>3)*3 的值是()
A. 0
B. true
C. 1
D. 3
答案:D(值为3)
解析:
- 布尔表达式的结果:在C++中,
5>3
是一个布尔表达式,判断结果为“真”(true
)。 - 布尔值与整数的转换:C++中,布尔值参与算术运算时会自动转换为整数——
true
转换为1
,false
转换为0
。 - 计算过程:
(5>3)*3
等价于true*3
,进一步转换为1*3=3
。 - 结论:表达式结果为3,对应选项D。
第2题 以下说法错误的是?
int a, b;
cin >> a >> b;
a = a*b;
b += a;
cout << a << " " << b << endl;
A. 输入 2 3,程序输出:6 9
B. 输入 1 1,程序输出:2 2
C. a = a * b 替换成 a *= b,效果一样
D. b += a 替换成 b = b + a,效果一样
答案: B
解析: 当输入 1 1
时,执行 a = 1*1 = 1
,b = 1 + 1 = 2
,因此输出应为 1 2
,而非 2 2
。
第3题 想输出 ‘a’~'z’26个字母,横线处填()
for(int i=1; i <=26; i++) {
cout << ____ << endl;
}
A. char(‘a’ + i)
B. char(‘a’ - 1 + i)
C. ‘a’ - 1 + i
D. ‘a’ + i
答案: B
解析: 当 i=1
时,'a' - 1 + i = 'a'
,i=26
时对应 'z'
。通过 char()
强制转换为字符类型,确保输出字母而非ASCII码值。
第4题 以下说法错误的是()
int n;
cin >> n;
while(n>0)
{
cout << n % 10;
n /=10;
}
A. 输入 345,输出 543
B. 输入 100,输出 001
C. 输入任意非负整数,程序能依次输出该数从个位到最高位的所有数位
D. 如果把 n /=10这一句删掉,运行程序并输入 123,程序会死循环
答案: C
解析: 0
为非负整数,当输入为 0
时,n > 0
条件不成立,程序无输出,因此选项C中“任意非负整数”的描述错误。
第5题 运行程序并输入9,输出为()
#include<iostream>
using namespace std;
int a[15];
int main()
{
int n;
cin >> n;
a[1]=a[2]=1;
for(int i=3; i<=n; i++)
{
a[i] = a[i-1] + a[i-2];
}
cout << a[n];
return 0;
}
A.2
B.21
C.34
D.55
答案: C
解析: 程序实现斐波那契数列,输入 9
时计算得 a[9] = 34
。
二、编程题
第一题 探险装备采购
题目描述
探险队即将开启新的探险!出发之前,他们需要采购一些探险装备。探险队共有n
人,每人需要3个探照灯、1 个氧气瓶,4 捆安全绳。已知探照灯x
元一个,气瓶y
元一个,安全绳z
元一捆,请你写一个程序,帮助他们计算买探险装备总共需要花费多少钱。
输入描述
一行输入四个整数
n、x、y、z
,分别表示探险队人数、探照灯单价、氧气瓶单价、安全绳单价,整数之间用空格隔开。
输出描述
一个整数,代表购买装备的总花费。
样例输入
40 3 5 4
样例输出
1200
样例说明
40 × (3×3 + 1×5 + 4×4) = 1200
数据范围
2 ≤ n,x,y,z ≤ 100
题目解析
需计算每人所需装备的总费用,再乘以人数得到总花费:
- 每人费用:
3×x + 1×y + 4×z
; - 总花费:
n × (3x + y + 4z)
。
解题步骤
- 读取输入的
n、x、y、z
; - 计算每人的装备费用:
3*x + y + 4*z
; - 总花费 =
n × 每人费用
; - 输出总花费。
代码实现
#include <iostream>
using namespace std;
int main() {
// 输入探险队人数、探照灯单价、氧气瓶单价、安全绳单价
int n, x, y, z;
cin >> n >> x >> y >> z;
// 计算总花费:每人需要3个探照灯、1个氧气瓶、4捆安全绳
int total = n * (3 * x + y + 4 * z);
// 输出总花费
cout << total << endl;
return 0;
}
知识点总结
- 算术运算:通过乘法和加法计算总费用;
- 输入输出:使用
cin
读取输入,cout
输出结果; - 公式推导:将实际问题转化为数学公式(总花费 = 人数 × 每人费用)。
第二题 地形判断
题目描述
探险队勘探宝藏埋藏之地的地形,测量了东侧、中央、西侧三个关键点的海拔高度,需要编写程序,根据输入的三个点海拔高度判断地形,地形分类如下:
- 1 山丘:中央高于东侧和西侧。
- 2 谷地:中央低于东侧和西侧。
- 3 平原:东侧、中央、西侧高度相同。
- 4 东侧坡:西侧高于中央,中央高于东侧。
- 5 西侧坡:东侧高于中央,中央高于西侧。
- 6 普通地形:不属于以上五种的任意一种。
输出要求
- 如果是山丘,输出
"hill"
- 如果是谷地,输出
"valley"
- 如果是平原,输出
"plain"
- 如果是西侧坡,输出
"west"
- 如果是普通地形,输出
"common"
输入描述
输入三个整数
a、b、c
,用空格隔开,分别表示东侧、中央、西侧的海拔高度。
输出描述
输出一个字符串,为
"hill" "valley" "plain" "east" "west" "common"
中的一个。
样例输入
60 60 60
样例输出
plain
数据范围
1 ≤ a,b,c ≤ 1000
题目解析
通过条件判断区分地形类型:
- 山丘:
b > a && b > c
; - 谷地:
b < a && b < c
; - 平原:
a == b && b == c
; - 东侧坡:
c > b && b > a
; - 西侧坡:
a > b && b > c
; - 其他情况为普通地形。
解题步骤
- 读取输入的
a、b、c
; - 通过
if-else
分支判断地形类型; - 输出对应的地形字符串。
代码实现
#include <iostream>
using namespace std;
int main() {
// 输入东侧、中央、西侧海拔
int a, b, c;
cin >> a >> b >> c;
// 按条件判断地形
if (b > a && b > c) { // 山丘:中央高于东侧和西侧
cout << "hill" << endl;
} else if (b < a && b < c) { // 谷地:中央低于东侧和西侧
cout << "valley" << endl;
} else if (a == b && b == c) { // 平原:三者高度相同
cout << "plain" << endl;
} else if (c > b && b > a) { // 东侧坡:西侧>中央>东侧
cout << "east" << endl;
} else if (a > b && b > c) { // 西侧坡:东侧>中央>西侧
cout << "west" << endl;
} else { // 普通地形
cout << "common" << endl;
}
return 0;
}
知识点总结
- 多条件分支:使用
if-else
处理复杂条件判断; - 逻辑运算:通过
&&
(逻辑与)组合多个条件; - 字符串输出:根据条件输出不同的字符串结果。
第三题 藏宝地宫探险
题目描述
探险队即将进入藏宝地宫。地宫由n
个区域组成,编号1~n,探险队用高科技探明了每个区域的宝藏数量a₁,a₂,…,aₙ
。同时,他们也发现有些区域隐藏着机关,n个区域的机关的伤害值用b₁,b₂,…,bₙ
表示,如果编号为i
的区域没有机关,则bᵢ=0
。如果踏入了有机关的区域,不仅无法获得该区域的宝藏,还会受到相应的伤害值。
探险队准备了一个防御值为k
的护盾抵挡伤害,如果探险队依次经过编号1~n区域的过程中受到的伤害总量超过了护盾的防御值k
,则本次探险过于危险,输出“Danger”
,结束探险。如果探险队依次经过编号1~n的全部区域受到的伤害总量没有超过护盾的防御值k
,则输出获得的宝藏总数。
输入
第1行:两个空格隔开的正整数
n
和k
,表示区域个数和护盾防御值。
第2行:n
个非负整数a₁,a₂,…,aₙ
,aᵢ
表示编号为i
的区域的宝藏数量。
第3行:n
个非负整数b₁,b₂,…,bₙ
,bᵢ
表示编号为i
的区域的机关伤害值。
输出
一个整数表示获得的宝藏总数,或者一个字符串
“Danger”
。
数据范围
1<=n<=1000,1<=k<=10000,0<=aᵢ,bᵢ<=100
输入样例1
5 6
4 1 9 4 2
0 3 0 1 2
输出样例1
13
输入样例2
4 3
3 7 2 1
0 2 2 0
输出样例2
Danger
题目解析
需模拟探险队经过每个区域的过程:
- 累加每个区域的伤害值,若超过
k
则输出“Danger”
; - 若区域无机关(
bᵢ=0
),则累加宝藏数量; - 遍历完所有区域后,输出宝藏总数。
解题步骤
- 读取输入的
n、k
,以及宝藏数组a
和伤害数组b
; - 遍历每个区域,累加伤害值和宝藏数量;
- 若伤害值超过
k
,输出“Danger”
并结束; - 否则输出宝藏总数。
代码实现
#include <iostream>
using namespace std;
int main() {
// 输入区域个数n和护盾防御值k
int n, k;
cin >> n >> k;
// 输入宝藏数量数组和机关伤害数组
int a[1005], b[1005];
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n; i++) cin >> b[i];
int harm = 0; // 累计伤害值
int treasure = 0; // 累计宝藏数
bool danger = false; // 是否触发危险
for (int i = 0; i < n; i++) {
harm += b[i]; // 累加当前区域的伤害
// 如果伤害超过护盾值,标记危险并退出循环
if (harm > k) {
danger = true;
break;
}
// 无机关(伤害值为0)时,累加宝藏
if (b[i] == 0) {
treasure += a[i];
}
}
// 输出结果
if (danger) {
cout << "Danger" << endl;
} else {
cout << treasure << endl;
}
return 0;
}
知识点总结
- 数组遍历:使用循环遍历宝藏和伤害数组;
- 条件判断:根据伤害值和机关状态决定是否累加宝藏;
- 状态标记:使用布尔变量标记是否触发危险。
第四题 回文书名统计
题目描述
古代王国的尚经阁里藏着许多奇怪的书籍,这些书籍的标题都是由小写字母组成的字符串。其中一些书籍比较特殊,书名是回文串(无论从左往右读还是从右往左读都一样)。这些特殊的书籍可能记录着上古的秘密。由于书籍太多,你需要写一个程序来统计回文书名的数量,并将所有回文书名按输入先后顺序连在一起输出。
输入
第一行,一个正整数
n
,表示共有n
本书,
接下来n
行,每行一个字符串,表示书名。每个字符串由小写字母组成,不包含空格。
输出
第一行输出一个整数,表示回文书名的个数。
第二行输出一个字符串,所有回文书名依次连在一起的结果,中间没有空格。如果不存在回文书名,则不输出。
数据范围
1<=n<=100,每个字符串长度不超过50。
输入样例
5
level
world
kayak
hello
civic
输出样例
3
levelkayakcivic
题目解析
需判断每个书名是否为回文串,并统计结果:
- 回文串判断:双指针法(从两端向中间比较字符);
- 统计回文串数量,并拼接结果。
解题步骤
- 读取输入的
n
和书名; - 对每个书名,使用双指针法判断是否为回文串;
- 统计回文串数量,并拼接结果;
- 输出数量和拼接后的字符串。
代码实现
#include <iostream>
#include <string>
using namespace std;
// 判断字符串是否为回文
bool isPalindrome(string s) {
int left = 0, right = s.size() - 1;
while (left < right) {
// 双指针从两端向中间比较
if (s[left] != s[right]) return false;
left++;
right--;
}
return true;
}
int main() {
int n;
cin >> n; // 输入书籍数量
int cnt = 0; // 回文书名数量
string result; // 回文书名拼接结果
for (int i = 0; i < n; i++) {
string s;
cin >> s; // 输入书名
if (isPalindrome(s)) { // 判断是否回文
cnt++;
result += s; // 拼接回文书名
}
}
// 输出结果
cout << cnt << endl;
if (cnt > 0) {
cout << result << endl;
}
return 0;
}
知识点总结
- 回文串判断:双指针法高效判断字符串是否为回文;
- 字符串拼接:使用
+=
操作拼接回文书名; - 函数封装:将回文判断逻辑封装为函数,代码更清晰。
第五题 神秘地宫宝石
题目描述
探险队进入了一个神秘地宫,里面有 n
堆宝石,每堆宝石个数为正整数,旁边有一面石碑,上面刻着取宝石的规则:
探险者需要选定一堆宝石,从这堆宝石开始每隔 k
堆宝石拿一堆宝石,选准一堆宝石,选取的那堆会受到神秘力量的惩罚!
已知每一堆宝石的数量,请问探险队最多能拿走多少个宝石?
输入描述
第一行:两个正整数
n、k
,用一个空格隔开;
第二行:n
个正整数a₁, a₂, …, aₙ
,表示每堆宝石的个数。
输出描述
一个整数,表示最多能拿走的宝石个数。
样例 1
输入
7 2
4 6 2 1 10 1 3
输出
16
提示
【样例说明】
从第 1 堆宝石开始拿,拿走第 1、4、7 堆宝石,总数为 8
从第 2 堆宝石开始拿,拿走第 2、5 堆宝石,总数为 16
从第 3 堆宝石开始拿,拿走第 3、6 堆宝石,总数为 3
从第 4 堆宝石开始拿,拿走第 4、7 堆宝石,总数为 4
从第 5 堆宝石开始拿,拿走第 5 堆宝石,总数为 10
从第 6 堆宝石开始拿,拿走第 6 堆宝石,总数为 1
从第 7 堆宝石开始拿,拿走第 7 堆宝石,总数为 3
数据范围
60% 的数据:1 ≤ n ≤ 10³,1 ≤ k ≤ 10³,且 k 不超过 100
每堆宝石个数不超过 10⁵。
60% 数据:枚举 n 个位置,每 k 个选一个,求总分最大量,O(n²/k)
100% 数据:枚举前 k-1 个位置,O(n)
题目解析
需枚举所有可能的起始堆,计算每种起始堆能拿到的宝石总数,取最大值:
- 起始堆范围:前
k
堆(避免重复计算); - 对于每个起始堆,每隔
k
堆取一次宝石(步长为k+1
); - 累加宝石数量,更新最大值。
解题步骤
- 读取输入的
n、k
和宝石数组a
; - 枚举前
k
个起始堆(start
从 0 到k
); - 对于每个起始堆,按步长
k+1
遍历数组,累加宝石数量; - 更新最大宝石数量;
- 输出最大值。
代码实现
#include <iostream>
using namespace std;
int main() {
int n, k;
// 读取输入的两个整数:
// n 表示宝石堆数量
// k 表示间隔的堆数(即每次跳过 k 个堆)
cin >> n >> k;
int a[1001]; // 定义数组 a[],用于存储每一堆宝石的数量,最多支持 1000 堆
// 读取每一堆宝石的数量
for (int i = 0; i < n; i++) {
cin >> a[i]; // 输入第 i 堆的宝石数量,存入数组 a[]
}
int max_sum = 0; // 记录所有方案中,最多能拿到的宝石总数,初始为 0
// 遍历所有可能的起始点
// 注意:我们只需要枚举前 k+1 个位置作为起始点(即下标 0 到 k)
// 因为跳跃步长为 k+1,如果从更靠后的点开始,路径就会过短或重复
for (int start = 0; start <= k && start < n; start++) {
int sum = 0; // 当前起点路径下能拿到的宝石数
// 从当前起点出发,每次跳过 k 个堆,即步长为 k+1
// 直到跳出数组范围
for (int i = start; i < n; i += k + 1) {
sum += a[i]; // 累加当前位置的宝石数
}
// 如果当前路径得到的宝石数比当前最大值大,更新最大值
if (sum > max_sum) {
max_sum = sum;
}
}
// 输出最终得到的最多宝石总数
cout << max_sum << endl;
return 0; // 程序正常结束
}
题目解析
核心逻辑是枚举所有可能的起始堆,计算每种情况下能拿到的宝石总数:
- 从第
start
堆开始,每次间隔k
堆(即步长为k+1
)选取宝石; - 由于步长固定,枚举前
k+1
个起始堆即可覆盖所有可能的路径(避免重复计算); - 累加每个路径的宝石数量,取最大值作为结果。
知识点总结
- 循环嵌套:外层循环枚举起始堆,内层循环按步长取宝石;
- 优化思想:通过限制起始堆范围(前
k+1
个)减少计算量; - 最值求解:使用变量
max_sum
记录并更新最大宝石数量。