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

第九届蓝桥杯省赛 C++ A组 - 付账问题

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:蓝桥杯题解集合
📝原题地址:付账问题
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

问题描述

几个人一起出去吃饭是常有的事。

但在结帐的时候,常常会出现一些争执。

现在有 n 个人出去吃饭,他们总共消费了 S 元。

其中第 i 个人带了 ai 元。

幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?

为了公平起见,我们希望在总付钱量恰好为 S 的前提下,最后每个人付的钱的标准差最小。

这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是 1 分钱的整数倍。

你需要输出最小的标准差是多少。

标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的“偏差有多大”。

形式化地说,设第 i 个人付的钱为 bi 元,那么标准差为 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OHTOg5ng-1673831661293)(AcWing 蓝桥杯辅导.assets/19_6734517a16-p1.png)]

输入格式

第一行包含两个整数 n、S;

第二行包含 n 个非负整数 a1, …, an。

输出格式

输出最小的标准差,四舍五入保留 4 位小数。

数据范围

1≤n≤5×105,
0≤ai≤109,
0≤S≤1015

输入样例1:

5 2333
666 666 666 666 666

输出样例1:

0.0000

输入样例2:

10 30
2 1 4 7 4 8 3 6 4 7

输出样例2:

0.7928

思路

由题可知,标准差的公式如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BicCoebY-1673831661297)(AcWing 蓝桥杯辅导.assets/image-20221227144755868.png)]

根据均值不等式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C15fBwtq-1673831661300)(AcWing 蓝桥杯辅导.assets/image-20221227144833252.png)]

可知 x 1 + x 2 + . . . + x n x_1+x_2+...+x_n x1+x2+...+xn 等价于 ( b 1 − s / n ) 2 + ( b 2 − s / n ) 2 + . . . + ( b n − s / n ) 2 (b_1-s/n)^2+(b_2-s/n)^2+...+(b_n-s/n)^2 (b1s/n)2+(b2s/n)2+...+(bns/n)2 ,又因为 b 1 + b 2 + . . . + b n = s b_1+b_2+...+b_n=s b1+b2+...+bn=s s / n ∗ n = s s/n*n=s s/nn=s,故 b 1 − s / n + b 2 − s / n + . . . + b n − s / n = s − s = 0 b_1-s/n+b_2-s/n+...+b_n-s/n=s-s=0 b1s/n+b2s/n+...+bns/n=ss=0

所以我们可以得出如下结论:

  1. a i > = s / n a_i>=s/n ai>=s/n 时,取平均数,这里可由上面等式推出。
  2. a i < s / n a_i<s/n ai<s/n 时, b i = a i b_i=a_i bi=ai b i < a i b_i<a_i bi<ai,这里可由两个值的均值不等式推出(证明略)。

总的来说,就是如果带的钱够交总花费的平均数就至少交这个平均数;如果不够则有多少出多少,然后将平均数与其差值分摊到其他人身上即让别人帮你垫。

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 500010;
int a[N];
int n;

int main()
{
    long double s;
    cin >> n >> s;
    for (int i = 0; i < n; i++)    scanf("%d", &a[i]);
    sort(a, a + n);    //对携带金额进行排序

    //钱多的人扶持钱少的人
    long double res = 0, avg = s / n;
    for (int i = 0; i < n; i++)
    {
        long double cur = s / (n - i);
        if (a[i] < cur)    cur = a[i];
        res += (cur - avg) * (cur - avg);
        s -= cur;
    }

    //打印结果
    printf("%.4Lf\n", sqrt(res / n));

    return 0;
}

相关文章:

  • 一个购物交易网站怎么做/互联网推广销售是做什么的
  • 成都网站外包公司/宁波网络营销怎么做
  • 网站做的好的/成都网站搭建优化推广
  • 一级a做爰片 A视频网站/网页设计首页
  • 沈阳网站建设专家/百度seo优化是做什么的
  • 辽宁省城乡和建设厅网站/吉林seo网络推广
  • 从汇编的角度了解C++原理——类的储存结构和函数调用
  • 双向bfs-字串变换
  • 软考报名有没有学历要求?2023年软考报名条件分享
  • linux下调节GPU的功率限制
  • 冥想第六百七十五天
  • 牛客竞赛每日俩题 - 动态规划4
  • python 列表生成式
  • MongoDB面试题整理-四年经验
  • 机器学习笔记之深度玻尔兹曼机(一)玻尔兹曼机系列整体介绍
  • 【Linux】探索缓冲区的概念 | Git 三板斧 | 实现简易进度条
  • JS语言基础
  • 详解分布式系统核心概念——CAP、CP和AP