当前位置: 首页 > news >正文

蓝桥杯 成绩统计

成绩统计

问题描述

小蓝的班上有 n 个人,一次考试之后小蓝想统计同学们的成绩,第 i 名同学的成绩为 a[i]。当小蓝统计完前 x 名同学的成绩后,他可以从 1 ∼ x 中选出任意 k 名同学的成绩,计算出这 k 个成绩的方差。小蓝至少要检查多少个人的成绩,才有可能选出 k 名同学,他们的方差小于一个给定的值 T

方差计算公式

k 个数 v1, v2, ..., vk 的方差 σ² 定义为:

σ² = (1 / k) * Σ(v[i] - v̄)²   (i = 1, 2, ..., k)

其中, 表示 v 的平均值,计算公式为:

v̄ = (1 / k) * Σv[i]   (i = 1, 2, ..., k)

输入格式

  • 第一行包含三个正整数 n, k, T,相邻整数之间使用一个空格分隔。
  • 第二行包含 n 个正整数 a1, a2, ..., an,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示答案。如果不能满足条件,输出 -1

样例输入

5 3 1
3 2 5 2 3

样例输出

4

样例说明

  • 检查完前三名同学的成绩后,选出的成绩是 3, 2, 5,方差为 1.56。
  • 检查完前四名同学的成绩后,选出的成绩是 3, 2, 2,方差为 0.33 < 1,符合要求,因此答案为 4

评测用例规模与约定

对于 10% 的评测用例,保证 1 ≤ n, k ≤ 10²
对于 30% 的评测用例,保证 1 ≤ n, k ≤ 10³
对于所有评测用例,保证 1 ≤ n, k ≤ 10⁵1 ≤ T ≤ 2³¹ - 1

c++代码

#include<bits/stdc++.h>

using namespace std;

long long n, k, T, g_left, g_right, x, ans, ex2, ex;
vector<long long> grades, middle, sum_ex, sum_ex2;

int judge() {
    middle = vector<long long>(x + 1);
    sum_ex = vector<long long>(x + 1, 0);
    sum_ex2 = vector<long long>(x + 1, 0);
    for (int i = 0; i <= x; i++) {
        middle[i] = grades[i];
    }
    sort(middle.begin(), middle.end());
    sum_ex[0] = middle[0];
    sum_ex2[0] = middle[0] * middle[0];
    for (int i = 1; i <= x; i++) {
        sum_ex[i] = middle[i] + sum_ex[i - 1];
        sum_ex2[i] = middle[i] * middle[i] + sum_ex2[i - 1];
    }
    for (int i = k - 1; i <= x; i++) {
        if (i - k >= 0) ex2 = sum_ex2[i] - sum_ex2[i - k];
        else ex2 = sum_ex2[i];
        if (i - k >= 0) ex = sum_ex[i] - sum_ex[i - k];
        else ex = sum_ex[i];
        if (ex2 * k - (ex)*(ex) < T * k * k) return 1;
    }
    return 0;
}

int main() {
    cin >> n >> k >> T;
    grades = vector<long long>(n);
    for (int i = 0; i < n; i++) {
        cin >> grades[i];
    }
    g_left = k - 1;
    g_right = n - 1;
    ans = -2;
    while (g_right >= g_left) {
        x = (g_left + g_right) / 2;
        if (judge() == 1) {
            g_right = x - 1;
            ans = x;
        }
        else g_left = x + 1;
    }
    cout << ans + 1<< endl;
}//by wqs

题目解析

你要找出最小的x需要二分查找策略,否则超时。

x确定之后就要给前x个数排序。

因为方差最小的k个数肯定是连续(从小到大排序)的k个数,我们要从所有连续的k个数里面判断方差是否小于T。

如果都大于等于T,说明前x个数不行。

只要有一个小于T,说明前x个数可以。

方差的计算用D(x) = e(x^2) - e(x)^2;

代码实现

二分策略查找x
g_left = k - 1;//左边界
g_right = n - 1;//右边界
ans = -2;
while (g_right >= g_left) {
    x = (g_left + g_right) / 2; //中间值
    if (judge() == 1) { //判断这个x是否可行
        g_right = x - 1;//可行更新右边界
        ans = x;
    }
    else g_left = x + 1;//不可行更新左边界
}
前x个数排序

因为方差最小的k个数肯定是连续(从小到大排序)的k个数,我们要从所有连续的k个数里面判断方差是否小于T。

middle = vector<long long>(x + 1);
for (int i = 0; i <= x; i++) {
    middle[i] = grades[i];
}
sort(middle.begin(), middle.end());
计算前x个所有连续k个数的方差
sum_ex sum_ex2简化运算

方差的计算用D(x) = e(x^2) - e(x)^2;

sum_ex存储前x个数的和, sum_ex2存储前x个数的平方和。

令ex2 = sum_ex2[i] - sum_ex2[i - k];

令ex = sum_ex[i] - sum_ex[i - k];

则e(x^2) = ex2 / k;

e(x) = ex / k;

这样我们计算e(x^2) 、e(x) 方便多了

sum_ex[0] = middle[0];
sum_ex2[0] = middle[0] * middle[0];
for (int i = 1; i <= x; i++) {
    sum_ex[i] = middle[i] + sum_ex[i - 1];
    sum_ex2[i] = middle[i] * middle[i] + sum_ex2[i - 1];
}
计算方差

令ex2 = sum_ex2[i] - sum_ex2[i - k];

令ex = sum_ex[i] - sum_ex[i - k];

则e(x^2) = ex2 / k;

e(x) = ex / k;

e(x^2) - e(x)^2 < T等价于

ex2 * k - ex*ex < T * k * k

这样我们就避免了使用除法,可以全部用整数了。

for (int i = k - 1; i <= x; i++) {
    if (i - k >= 0) ex2 = sum_ex2[i] - sum_ex2[i - k];
    else ex2 = sum_ex2[i];
    if (i - k >= 0) ex = sum_ex[i] - sum_ex[i - k];
    else ex = sum_ex[i];
    if (ex2 * k - (ex)*(ex) < T * k * k) return 1;
}

如果都大于等于T,说明前x个数不行。

只要有一个小于T,说明前x个数可以。

相关文章:

  • PhotoDoodle: Learning Artistic Image Editing from Few-Shot Examples 论文解读
  • 两个桌面图标助手,你喜欢哪一个
  • uniapp vue3实现的一款数字动画调节器件,支持长按、单点操作,提供丝滑的增减动画效果
  • 03.04、化栈为队
  • 次日留存率——mysql计算过程
  • 【北大Deepseck】最新2份pdf(附不限速链接) 系列-提示词工程和落地场景 DeepSeek与AIGC应用
  • 【FL0087】基于SSM和微信小程序的民宿短租系统
  • Qt之3D绘制曲线:QtDataVisualization实时绘制散点图
  • 网络原理--IP协议简介
  • Git简单操作
  • EasyRTC嵌入式WebRTC技术与AI大模型结合:从ICE框架优化到AI推理
  • java练习(45)
  • 惯导(机械编排)算法(INS Mechanization)_预备知识笔记
  • 大语言模型的评测
  • server.servlet.session.timeout: 12h(HTTP 会话的超时时间为 12 小时)
  • # C# 中堆(Heap)与栈(Stack)的区别
  • 一文掌握使用深度学习识别验证码详解(包括图形验证码和滑块验证码)
  • Delphi 12.3 函数指针(函数可以当参数)
  • 7.1 线性代数进行图像处理
  • 【博资考4】网安学院-硕转博考试内容
  • 中国戏剧梅花奖终评结果公示,蓝天、朱洁静等15名演员入选
  • 武汉警方通报一起故意伤害案件:1人死亡,嫌疑人已被抓获
  • 历史缝隙里的人︱觑功名如画饼:盛世“做题家”的攀爬与坠落
  • 俄媒:俄乌伊斯坦布尔谈判将于北京时间今天17时30分开始
  • “养胃骗局”大公开,真正有用的方法究竟是?
  • 由我国牵头制定,适老化数字经济国际标准发布