题解:学而思编程 体育课
【题目来源】
学而思编程:体育课
【题目描述】
小猴是学校的体育器材的管理员,现在因为器材老化需要购买一批新的体育器材,具体每一种体育器材需要购买多少取决于当前学期每一种器材的借用情况。
小猴发现这学期的体育选修课只有三类:羽毛球、乒乓球和篮球。现在小猴请你根据这学期的体育课情况来统计一下这学期一共借出了多少器材(只包含羽毛球、乒乓球和篮球),每种器材分别借出的多少次,每种器材借出次数占所有器材借出总次数的百分比分别是多少。
【输入】
第一行一个整数 \(n\),表示这学期体育课的次数。
接下来 \(n\) 行,每行两个整数 \(a_i\) (表示第 \(i\) 节体育课借用器材的次数)和 \(b_i\)(表示第 \(i\) 节体育课借用的器材种类,\(0\) 表示羽毛球,\(1\) 表示乒乓球,\(2\) 表示篮球)。
【输出】
一共有 \(3\) 行:
第一行一个整数表示一共借出了多少器材;
第二行三个空格隔开整数分别表示羽毛球、乒乓球和篮球这学期借出的次数;
第三行三个空格隔开百分数表示羽毛球、乒乓球和篮球借出次数占所有器材总借出次数的占比值,占比值保留两位小数。
【输入样例】
10
10 0
6 1
15 2
5 0
14 1
9 0
6 1
8 2
5 0
14 1
【输出样例】
92
29 40 23
31.52% 43.48% 25.00%
【核心思想】
-
问题分析:给定 \(n\) 节体育课,每节课借用 \(a_i\) 次器材,器材类型为 \(b_i\)(\(0\) 羽毛球、\(1\) 乒乓球、\(2\) 篮球)。需要统计总借用次数、每类器材借用次数及占比。这是一个分类统计问题,关键在于用数组索引映射器材类型,实现 \(O(1)\) 的分类累加。
-
算法选择:
- 桶计数(Bucket Counting):用数组 \(cnt[0..2]\) 分别对应三类器材的累计借用次数
- 前缀累加:边读入边累加,无需存储所有数据
-
关键步骤:
- 初始化:\(cnt[0] = cnt[1] = cnt[2] = 0\),\(sum = 0\)
- 逐条处理(循环 \(n\) 次):
- 读取 \(a_i\)(借用次数)和 \(b_i\)(器材类型)
- 分类累加:\(cnt[b_i] \leftarrow cnt[b_i] + a_i\)
- 累计总数:\(sum \leftarrow sum + a_i\)
- 输出结果:
- 第一行:输出 \(sum\)
- 第二行:依次输出 \(cnt[0]\)、\(cnt[1]\)、\(cnt[2]\)
- 第三行:对 \(i = 0, 1, 2\),计算并输出 \(cnt[i] \times 100.00 / sum\),保留两位小数,格式为百分比
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),只需一次遍历 \(n\) 条记录
- 空间复杂度:\(O(1)\),仅需固定大小的 \(cnt\) 数组和 \(sum\) 变量
-
分类统计的核心思想:
- 索引映射:利用器材类型编号 \(b_i \in \{0, 1, 2\}\) 直接作为数组下标,实现 \(O(1)\) 的定位和累加,避免繁琐的
if-else分支判断 - 在线处理:读入一条处理一条,无需存储全部输入数据,节省空间
- 百分比计算:\(cnt[i] \times 100.00 / sum\) 将计数转换为百分比,注意使用浮点除法(乘 \(100.00\) 而非 \(100\))保证精度
- 格式化输出:使用
%.2f%%控制保留两位小数并输出百分号,确保输出格式符合要求 - 适用于多类别数据统计、频率分布计算、分类汇总类问题
- 索引映射:利用器材类型编号 \(b_i \in \{0, 1, 2\}\) 直接作为数组下标,实现 \(O(1)\) 的定位和累加,避免繁琐的
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, cnt[5]; // cnt数组用于统计不同类型(0,1,2)的数量
int main()
{
cin >> n;
int sum = 0; // 记录总数
for (int i = 1; i <= n; i++)
{
int a, b;
cin >> a >> b; // a: 数量, b: 类型
cnt[b] += a; // 累加到对应类型
sum += a; // 累加到总数
}
// 输出总数
cout << sum << endl;
// 输出各类别的数量
for (int i = 0; i <= 2; i++)
{
cout << cnt[i] << " ";
}
cout << endl;
// 输出各类别占总数的百分比
for (int i = 0; i <= 2; i++)
{
printf("%.2f%% ", cnt[i] * 100.00 / sum);
}
return 0;
}
【运行结果】
10
10 0
6 1
15 2
5 0
14 1
9 0
6 1
8 2
5 0
14 1
92
29 40 23
31.52% 43.48% 25.00%
浙公网安备 33010602011771号