首页 > 其他分享 >「数学」付账问题

「数学」付账问题

时间:2023-07-15 10:45:49浏览次数:41  
标签:ave int 平均数 付账 问题 平摊 数学 double 标准差

本题蓝桥OJ第174题的题解(蓝桥OJ上的相同题解也是我发的)

题面

题目描述

几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。现在有n个人出去吃饭,他们总共消费了S元。其中第i个人带了 \(a_i\) 元。幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?为了公平起见,我们希望在总付钱量恰好为S的前提下,最后每个人付的钱的标准差最小。这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是1分钱的整数倍。你需要输出最小的标准差是多少。

标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的"偏差有多大"。形式化地说,设第i个人付的钱为 $ b_i $元,那么标准差为: $ \sqrt{\frac{1}{n}\sum_{i=1}{n}(b_i-\frac{1}{n}\sum_{i=1})^2b_i}$​

输入

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

第二行包含n个非负整数 \(a_1,\dots,a_n\) 。
其中, \(n \leq 5 \times 10^5\), \(0 \leq a_i \leq 10^9\) 。

输出

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

保证正确答案在加上或减去 \(10_{-9}\) 后不会导致四舍五入的结果发生变化。

样例输入

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

样例输出

0.7928

思路分析

想要标准差变小,只需要让每个人付的钱足够接近即可.显然,如果每个人都付平均数的钱,那标准差就是最小的0.

但是实际上会普遍存在有人钱不够付平均数的情况,这时这个人只能把他有的钱全付了,而他少付的钱只能由钱比他多的人来付.显然,想让这种情况下的标准差变小,这个少付的钱也需要平摊(每个人付平均数),即在原本平摊总额平均数的同时再平摊前面人少付的钱.这也相当于说,后面的人需要付当前还需要付的钱的总额的平均数.

如果后面的人的钱不够付这个新的平均数,那么同样处理,后面的人继续平摊少付的那部分.

所以我们只需要将所有人有的钱升序排序,这样可以始终先处理钱不够的人.我们不断维护剩下需要付的钱的总额,然后累加方差中的那个累加式即可.当有人的钱购付时,由于已排序,后面的人一定也购付,此时后面的人全部支付当前平均数的钱,直接统一计算即可.

参考代码

时间复杂度: \(O(nlogn)\)

空间复杂度: \(O(n)\)

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")
#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    i64 n, s;
    cin >> n >> s;

    int *a = new int[n];
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    sort(a, a + n);

    double ave = (double)s / n;  // 计算标准差时所需要使用的所有人付钱总额的平均数
    double sum = 0; // 方差中累加式的结果
    for (int i = 0; i < n; i++) {
        if (a[i] * (n - i) < s) {  // 不足支付当前平摊后的平均数
            sum += (a[i] - ave) * (a[i] - ave);  // 把此人有的钱全部支付
            s -= a[i];
        } else {  // 从当前人开始,够支付当前平摊后的平均数
            double money = (double)s / (n - i); // 当前平摊后的平均数,即当前人开始所有人付的钱
            sum += (money - ave) * (money - ave) * (n - i); // 直接统一计算
            break;
        }
    }

    cout << fixed << setprecision(4) << sqrt(sum / n);

    delete[] a;

    return 0;
}

"正是我们每天反复做的事情,最终造就了我们,优秀不是一种行为,而是一种习惯" ---亚里士多德

标签:ave,int,平均数,付账,问题,平摊,数学,double,标准差
From: https://www.cnblogs.com/geministar/p/lanqiao_174.html

相关文章

  • 60.如何解决跨域问题
    60.如何解决跨域问题?相关知识点:通过jsonp跨域document.domain+iframe跨域location.hash+iframewindow.name+iframe跨域postMessage跨域跨域资源共享(CORS)nginx代理跨域nodejs中间件代理跨域WebSocket协议跨域回......
  • 99.为什么0.10.20.3如何解决这个问题
    99.为什么0.1+0.2!=0.3?如何解决这个问题?当计算机计算0.1+0.2的时候,实际上计算的是这两个数字在计算机里所存储的二进制,0.1和0.2在转换为二进制表示的时候会出现位数无限循环的情况。js中是以64位双精度格式来存储数字的,只有53位的有效数字,超过这个长度的位数会被......
  • 解决浏览器自动将http跳转至https导致无法访问的问题
      最近在宝塔面板申请免费的SSL证书后,部署证书的80端口下的网站可以通过https正常访问,但其他未部署证书的端口也被强制跳转至https请求,导致浏览器提示不安全从而无法访问。宝塔的8888端口也不能访问,当时那是一个慌,当我尝试了各种方法,如重新放行443端口、重新配置nginx反向代理、......
  • 浅谈树上问题
    树的直径定义规定树上任意两节点之间的最远距离为树的直径解法较为主流的解法有两种贪心以任意节点\(x\)为根进行一次\(\text{DFS}\),记录距\(x\)最远的节点编号为\(y\),再以\(y\)为根进行第二次\(\text{DFS}\),得到距\(y\)最远的节点编号\(z\),那么\(dis(x,......
  • 关于线程问题的探讨(售票问题)
    packageSellTickets;publicclassSellTickets01implementsRunnable{privatestaticintticketNum=100;@Overridepublicvoidrun(){while(true){if(ticketNum<=0){System.out.pr......
  • 修复域名访问问题
    研究了一下午,一开始思考为什么不能一直用域名访问,在主页面点进新页面后就不能继续使用域名访问了,所以就开始修复这个问题,问了问AI是反向代理服务器的问题,结果给我网站搞崩了,查了一堆资料还是没解决,结果自己随便逛了逛宝塔面板,看到PHP是静态的,我就知道问题了,妈的,还是自己的脑袋聪......
  • 配置问题-Error creating bean with name 'user' defined in class path resource [be
    正在学习IoC使用的jdk版本为jdk17依赖为:<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>6.0.6</version></dependen......
  • SQL注入问题、视图、触发器、事务、存储过程、函数、流程控制、索引、测试索引
    SQL注入问题连接MySQL服务器conn=pymysql.connect(host=‘127.0.0.1’port=3306user=‘root’password='1234'......
  • 了不起的魔术师问题
    目录了不起的魔术师问题前言问题描述解决方案参考了不起的魔术师问题前言此问题来自于<<Python编程:从入门到实践>>第一版中习题8-10.问题描述了不起的魔术师:创建一个包含魔术师名字的列表,并将其传递给一个名为show_magicians()的函数,这个函数打印列表中每个魔术......
  • Qt信号槽信号函数重载问题 error: C2664: “QMetaObject::Connection const”
    //connect(spinFontSize,&QSpinBox::valueChanged,this,&MainWindow::spinFontSize_valueChanged);//由于信号函数存在重载,发送者找不到正确信号函数。//改用A.Qt4带形参方式//connect(spinFontSize,SIGNAL(valueChanged(int)),this,SLOT(spinFontSize_valueChang......