【2024年莆田市校园创客节(小学组)初赛】期中考试
期中考试
题目描述
问题描述
班级有 a 名学生,b 门课程。已知每门课程的满分人数,求班上至少有多少人所有课程都考到满分(全满分人数最小值)。若不可能存在全满分学生,输出 0。
输入格式
- 第一行:两个正整数
a(学生总数)和b(课程数量); - 接下来
b行:每行一个整数s_i(第i门课程的满分人数)。
输出格式
一个整数,表示最少全满分人数。
样例输入输出
样例输入 1
40 5
33
36
30
28
39
样例输出 1
6
样例输入 2
55 3
16
30
25
样例输出 2
0
数据范围
- 30% 数据:
b = 2; - 100% 数据:
5 ≤ a ≤ 50000,1 < b ≤ a/2,0 ≤ s_i ≤ a。
解题思路
核心思想:贪心推导公式
要找最少全满分人数,核心是让非全满分学生尽可能多分担各课程满分名额,从而减少全满分人数。
公式推导关键步骤
- 设全满分人数为
x,则每门课程剩余满分名额为s_i - x(由非全满分学生承担); - 非全满分学生共
a - x人,每人最多在b-1门课程得满分(否则就是全满分),最多能承担(a - x) * (b - 1)个满分名额; - 所有课程剩余满分名额总和 ≤ 非全满分学生最大承担量,化简后得到:
x ≥ 所有课程满分人数总和 - (b-1)*a; - 人数不能为负,最终答案为
max(总和 - (b-1)*a, 0)。
代码实现(一维数组版)
#include <iostream>
#include <algorithm> // 用于 max 函数
using namespace std;int main() {int a, b;cin >> a >> b;// 一维数组存储每门课程满分人数,b最大为25000(a<=5e4,b<=a/2),数组足够大int s[25005];int sum = 0;// 读取每门课程满分人数,累加总和for (int i = 0; i < b; i++) {cin >> s[i];sum += s[i];}// 核心公式计算,结果取非负int res = sum - (b - 1) * a;cout << max(res, 0) << endl;return 0;
}
代码解释
变量说明
a:学生总数,b:课程数量;s[25005]:一维数组,存储每门课程的满分人数(数组大小 25005 适配b<=a/2且a<=5e4的最大情况);sum:所有课程满分人数的总和;res:通过核心公式计算的最少全满分人数,最终用max(res, 0)确保结果非负。
核心逻辑
- 输入读取:先读
a和b,再用循环读b个满分人数存入数组,同时累加总和; - 公式计算:直接代入推导公式
sum - (b-1)*a; - 结果修正:避免人数为负,用
max函数取计算结果和 0 的较大值。
复杂度分析
- 时间复杂度:O(b),仅遍历
b次读取数据,效率极高; - 空间复杂度:O(b),一维数组存储
b个满分人数,空间占用极小。
测试用例验证
样例输入 1 验证
a=40,b=5,数组s = [33,36,30,28,39],总和sum=166;- 计算:
166 - 4*40 = 6,输出 6,与样例一致。
样例输入 2 验证
a=55,b=3,数组s = [16,30,25],总和sum=71;- 计算:
71 - 2*55 = -39,输出 0,与样例一致。
注意事项
- 数组大小:题目中
b<=a/2且a<=5e4,所以b最大为 25000,数组设为25005足够,避免越界; - 数据溢出:
(b-1)*a最大约 25000*50000=1.25e9,int类型(4字节)可容纳,无需担心溢出;
