2025年7月13日全国青少年信息素养大赛C++编程小学组复赛真题+答案解析
编程题
1. 种树
题目描述
学校组织植树活动,每个班级都需要种植固定数量的树苗。已知共有若干个班级参与。请问总共需要准备多少棵树苗?
输入描述
一行,两个正整数 m
和 n
,分别表示每个班级分到的树苗数量和班级数量
输出描述
一行,一个正整数,表示需要准备的树苗数量
样例输入:
5 3
样例输出:
15
题目解析
题目要求根据每个班级分配的树苗数量以及班级数量,计算出总共需要准备的树苗数,本质就是简单的乘法运算应用。
解题步骤
- 从输入获取每个班级分到的树苗数量
m
和班级数量n
。 - 通过乘法运算
m * n
得到总共需要准备的树苗数量。 - 输出计算得到的总树苗数量。
代码实现
#include <iostream>
using namespace std;
int main() {
int m, n;
// 从输入读取每个班级分到的树苗数量m和班级数量n
cin >> m >> n;
// 计算总树苗数量(每个班级数量 × 班级数量)
int tot = m * n;
// 输出总树苗数量
cout << tot << endl;
return 0 ;
}
知识点总结
- 输入输出:学会使用
cin
从控制台读取输入数据,使用cout
向控制台输出数据。 - 基本运算:掌握乘法运算在实际问题中的应用。
2. 整数分类
题目描述
给定 n
和 t
,将1到 n
之间的所有正整数分为两类: A 类数可以被 t
整除(也就是说是 t
的倍数),而 B 类数不能。请输出这两类数的和。
输入描述
一行,两个正整数 n
和 t
。
输出描述
一行,两个正整数,分别表示 A 类数的和、B 类数的和,两者用空格间隔。
样例1输入:
10 3
样例1输出:
18 37
解释:
A类数(3的倍数):3, 6, 9 → 和为3 + 6 + 9 = 18
B数(非3的倍数):1, 2, 4, 5, 7, 8, 10 → 和为1 + 2 + 4 + 5 + 7 + 8 + 10 = 37
样例2输入:
5 2
样例2输出:
6 9
解释:
A类数(2的倍数):2, 4 → 和为2 + 4 = 6
B类数(非2的倍数):1, 3, 5 → 和为1 + 3 + 5 = 9
题目解析
题目要求对1到 n
的整数按能否被 t
整除进行分类,并分别计算两类数的和,核心是对循环遍历和条件判断的运用。
解题步骤
- 从输入获取
n
和t
的值。 - 初始化两个变量
A
和B
分别用于存储A类数和B类数的和,初始值为0。 - 使用循环遍历1到
n
的每一个数i
:- 如果
i
能被t
整除,将i
加到A
中。 - 否则,将
i
加到B
中。
- 如果
- 输出
A
和B
的值,中间用空格隔开。
代码实现
#include <iostream>
using namespace std;
int main() {
int n, t, A = 0, B = 0;
// 从输入读取n和t的值
cin >> n >> t;
// 遍历1到n的每一个数
for (int i = 1; i <= n; i++) {
// 如果i能被t整除
if (i % t == 0) A += i;
else
// i不能被t整除
B += i;
}
// 输出A类数的和与B类数的和,中间用空格隔开
cout << A << " " << B << endl;
return 0;
}
知识点总结
- 循环结构:
for
循环用于遍历一定范围内的数。 - 条件判断:
if - else
语句用于判断数是否能被t
整除,从而进行分类求和。
3. 智慧农业监测系统
题目描述
某智慧农业监测系统需要根据作物生长周期动态调整灌溉方案。系统发现不同年份月份的灌溉天数计算模块存在误差,特别是闰年二月天数计算不准确。请编写程序实现历法校验功能,精确计算指定年份月份对应的自然日数。
输入描述
一行,两个正整数,分别表示年份 y
和月份 m
,用空格隔开。
输出描述
一行,一个正整数,表示这个月有多少天。
样例1输入:
2000 2
样例1输出:
29
样例2输入:
2023 4
样例2输出:
30
题目解析
本题重点在于根据闰年的判断规则来确定二月的天数,同时要明确其他月份固定的天数,考察对闰年概念和条件判断的掌握。
解题步骤
- 从输入获取年份
y
和月份m
。 - 创建一个数组
days
存储非闰年各月份的天数。 - 如果月份
m
是2月:- 根据闰年判断规则(年份能被4整除但不能被100整除,或者能被400整除)判断是否为闰年。
- 如果是闰年,输出29并结束程序。
- 如果不是2月或者不是闰年的2月,直接输出数组
days
中对应月份(m - 1
)的天数。
代码实现
#include <iostream>
using namespace std;
int main() {
int y, m;
// 从输入读取年份y和月份m
cin >> y >> m;
// 月份天数数组(非闰年)
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 如果月份是2月
if (m == 2) {
// 闰年判断:能被4整除但不能被100整除,或者能被400整除
if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) {
cout << 29;
return 0;
}
}
// 输出对应月份的天数
cout << days[m - 1];
return 0;
}
知识点总结
- 数组:用于存储非闰年各月份的天数。
- 闰年判断:掌握闰年的判断条件,并能在程序中用条件语句实现。
- 条件语句:
if - else
语句根据不同条件输出不同结果。
4. 星际通信系统
题目描述
在星际通信系统中,传输的数字会因宇宙射线干扰而倒序,请编写程序对接收到的 n
个干扰数字进行修复,输出每个数字原始的正确值。修复规则:将每个数字的各位数完全逆转(例如:123修复为321, 120修复为21)
输入描述
第一行,一个整数 n
。
第二行 n
个正整数 ai
,表示接收到的干扰数字。
输出描述
一行 n
个整数,表示修复后的正确数字,用空格分隔。
样例输入
3
123 320 78
样例输出
321 23 87
题目解析
题目要求对输入的 n
个数字按特定规则(各位数字逆转)进行修复,主要运用循环和数学运算来实现数字的逆转。
解题步骤
- 从输入获取数字的个数
n
。 - 定义一个函数
Rev
用于逆转单个数字:- 在函数中,初始化一个变量
ans
为0。 - 使用
while
循环,通过取余和整除操作,将数字的每一位逆转到ans
中。 - 输出逆转后的数字,并添加空格。
- 在函数中,初始化一个变量
- 定义一个数组
a
用于存储接收到的干扰数字。 - 从输入读取
n
个干扰数字存储到数组a
中。 - 遍历数组
a
,对每个数字调用Rev
函数进行逆转输出。
代码实现
#include <iostream>
using namespace std;
const int N = 1e8;
int a[N];
// 定义逆转单个数字的函数
void Rev(int x) {
int ans = 0;
// 通过循环将数字x的每一位逆转到ans中
while (x) {
ans = ans * 10 + x % 10;
x /= 10;
}
// 输出逆转后的数字,并添加空格
cout << ans << " ";
return;
}
int main() {
int n;
// 从输入读取数字的个数n
cin >> n;
// 从输入读取n个干扰数字存储到数组a中
for (int i = 0; i < n; i++) cin >> a[i];
// 遍历数组a,对每个数字调用Rev函数进行逆转输出
for (int i = 0; i < n; i++) Rev(a[i]);
return 0;
}
知识点总结
- 函数定义与调用:学会定义和调用自定义函数,这里定义
Rev
函数实现数字逆转。 - 循环结构:
while
循环用于数字逆转的过程。 - 数组:存储接收到的干扰数字。
5. 小球
题目描述
有 n
个小球摆成一排,第 i
个小球的颜色为 c
,在这一排小球中,你可以选择其中连续的 K
个小球并且获得他们。你喜欢五彩缤纷的颜色,所以你获得的小球不同颜色越多,就越高兴,输出你能获得的最多的小球颜色数。
输入描述
第一行,两个数字 n
和 k
,表示一共有多少个小球,以及你可以选择获得其中连续的 K
个小球。
第二行,n
个数字,表示每个小球的颜色 ci
。
输出描述
一行,一个整数,表示你能获得的最多小球的颜色数量。
样例输入1:
5 3
1 2 2 3 1
样例输出1
3
样例解释:
输入:n = 5
, k = 3
颜色:1 2 2 3 1
第一个窗口[0,2]:颜色[1,2,2] -> 不同颜色数为2(1和2)。
第二个窗口[1,3]:颜色[2,2,3] -> 不同颜色数为2(2和3)。
第三个窗口[2,4]:颜色[2,3,1] -> 不同颜色数为3(2,3,1)。
所以输出3。
数据范围
1 <= n
<= 3 * 10^5,1 <= ci
<= 1000
题目解析
本题使用滑动窗口算法,通过固定大小为 k
的窗口在小球颜色数组上滑动,统计每个窗口内不同颜色的数量,从而找出最多的不同颜色数。
解题步骤
- 从输入获取小球总数
n
和窗口大小k
。 - 定义两个数组
cs
用于存储每个小球的颜色,cnt
用于记录每种颜色在窗口内的数量。 - 特殊处理
k == 0
的情况,直接输出0并结束程序。 - 初始化第一个窗口(前
k
个元素):- 遍历前
k
个小球的颜色,使用cnt
数组记录每种颜色的数量。 - 如果一种颜色首次出现(
cnt[cs[i]] == 0
),则不同颜色数ans
加1。 - 记录此时窗口内不同颜色数的最大值
Max_ans
为ans
。
- 遍历前
- 使用循环滑动窗口,窗口长度为
k
:- 移除窗口最左侧的元素,更新其颜色计数(
cnt[cs[L]]--
)。如果计数降为0,则不同颜色数ans
减1。 - 添加窗口右侧的新元素,更新其颜色计数(
cnt[cs[R]]++
)。如果计数从0增加到1,则不同颜色数ans
加1。 - 更新不同颜色数的最大值
Max_ans
。
- 移除窗口最左侧的元素,更新其颜色计数(
- 输出
Max_ans
,即能获得的最多小球颜色数。
代码实现
#include <iostream>
using namespace std;
const int N = 1e6;
int cs[N], cnt[N];
int main() {
int n, k;
// 从输入读取小球总数n和窗口大小k
cin >> n >> k;
// 从输入读取每个小球的颜色存储到cs数组
for (int i = 0; i < n; i++) cin >> cs[i];
// 特殊处理k = 0的情况
if (k == 0) {
cout << 0 << endl;
return 0;
}
int ans = 0, Max_ans = 0;
// 初始化第一个窗口(前K个元素),统计窗口中不同颜色的数量。
for (int i = 0; i < k; i++) {
if (cnt[cs[i]] == 0) ans++;
cnt[cs[i]]++;
}
Max_ans = ans; // 最大值有颜色种类
// 滑动窗口,窗口长度为k
for (int L = 0; L < n - k; L++) {
int R = L + k;
// 移除窗口最左侧的元素,更新其颜色计数。如果计数降为0,则减少不同颜色的数量。
cnt[cs[L]]--;
if (cnt[cs[L]] == 0) ans--;
// 添加窗口右侧的新元素,更新其颜色计数。如果计数从0增加到1,则增加不同颜色的数量。
if (cnt[cs[R]] == 0) ans++;
cnt[cs[R]]++;
// 记录当前窗口中不同颜色的最大值
if (ans > Max_ans)
Max_ans = ans;
}
// 输出结果
cout << Max_ans << endl;
return 0;
}
知识点总结
- 滑动窗口算法:理解并掌握滑动窗口在数组上的应用,包括窗口的初始化、滑动以及数据的更新。
- 数组:两个数组
cs
和cnt
分别用于存储小球颜色和颜色计数。 - 条件判断:在更新窗口内颜色计数时,通过条件判断来确定不同颜色数的变化。