TODO -蓝桥杯2018年A组-付账问题

news/2024/5/19 21:25:02

0.题目

题目描述

几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。

现在有 \(n\) 个人出去吃饭,他们总共消费了 \(S\) 元。其中第 \(i\) 个人带了 \(a_i\) 元。幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?

为了公平起见,我们希望在总付钱量恰好为 \(S\) 的前提下,最后每个人付的钱的标准差最小。这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是 \(1\) 分钱的整数倍。你需要输出最小的标准差是多少。

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

输入格式

第一行包含两个整数 \(n\)\(S\)

第二行包含 \(n\) 个非负整数 \(a_1,\cdots,a_n\)

输出格式

输出到标准输出。

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

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

样例 #1

样例输入 #1

5 2333
666 666 666 666 666

样例输出 #1

0.0000

样例 #2

样例输入 #2

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

样例输出 #2

0.7928

提示

【样例解释】

  1. 每个人都出 2333/5 元,标准差为 0。

【数据约定】

对于 \(10\%\) 的数据,所有 \(a_i\) 相等;

对于 \(30\%\) 的数据,所有非 \(0\)\(a_i\) 相等;

对于 \(60\%\) 的数据,\(n \le 1000\)

对于 \(80\%\) 的数据,\(n \le 10^5\)

对于所有数据,\(n \le 5 \times 10^5,0 \le a_i \le 10^9\)

1.题解

1.1 贪心

思路

这里由于付钱总款固定, 人数固定, 所以平均值是固定的

总体思路使用到贪心的思想, 在尽可能使得每一步中每个人付的钱在后续足够的情况下,尽可能的少.
前面的不够(小于第一次计算的avg)后面的补上, 但当后面人总钱数大于(avg)的时候,我们就要考虑补多少

我们就可以考虑 还需要补的总钱数 / 剩余人数 = cur_avg(此种情况标准差最小);
可以这么思考, 我们在付完所有钱少于avg的人后, 如果我们希望剩余所有钱大于avg的人标准差最小, 有公式:
\((y_i - cur\_avg)^2 = (y_i - avg + avg - cur\_avg)^2 = (y_i - avg)^2 + 2(y_i - avg)(avg - cur\_avg) + (avg - cur\_avg)^2\)
我们可以发现(avg-cur_avg)是一个固定值且大于零, 又因为 \(y_i > avg, avg - cur\_avg < 0\),
所以当所有 \((y_i - cur\_avg)^2\) 和最小的时候, 也能得到所有 \((y_i - avg)^2\) 和最小
我们画个图就能明白, 设常数 a = cur_avg - avg, 当(范围: x = y_i - avg > 0 ) (x-a)^2 和 x^2 单调性是一样的, 在 (x-a)^2 取的最小值时, x^2 也能取到最小值

若是当前人所持钱少于cur_avg, 那么就进一步计算新的cur_avg, 直到当前人钱大于当前cur_avg, 后面所有人均付cur_avg即可

我们可以简单分析一下,若能让每个人在够付账的情况下付的金额尽可能集中就可以使得标准差最小。
举个例子假如n = 10 , S = 30,每个人金额分别为1 , 2 , 3 , 4 , 4 , 4 , 6 , 7 , 7 , 8
先求出均值avg = 4.6,再对金额进行排序。

1.当金额小于均值时需要付出所有的钱;
2.当金额大于或等于均值时,这个人以及之后的所有人都需要在第一步完成的基础上重新计算均值即为cur_avg

代码

#include<bits/stdc++.h>
#define ll long long
const int M = 5e5 + 1;
ll a[M];
using namespace std;
int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n;ll S;cin >> n >> S;for(int i = 1; i <= n; i++) {cin >> a[i];}sort(a+1, a+n+1);double avg = (S * 1.0) / n,  differ = 0;for(int i = 1; i <= n; i++) {// 钱够了,全部支付if (a[i] * (n - i + 1) >= S) {double remain_avg = S * 1.0 / (n-i+1);differ += (n - i + 1) * pow(remain_avg - avg, 2);break;} else {S -= a[i];differ += pow(a[i] - avg, 2);}}differ = sqrt(differ / n);printf("%.4lf", differ);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/25412.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

小伙伴:我是专升本,能不写在简历里吗?

大家好,我是树哥。 最近我推出了简历辅导服务(详见:500 块就能获得 10 年的行业经验,太赚了!),有一位同学找我做了简历辅导。 在阅读他的简历的时候,我发现他的学历没有写入学时间和毕业时间,感觉不是很直观,于是让他补全一下。小伙伴回复说:我是专升本的,本科只有…

Jetpack Compose 中如何实现全面屏

看问题本质,设置全面屏,是系统窗口的行为,与 View 和 Compose 有什么关系呢? 所以,原理和传统 View 视图是一样的,甚至 Api 都是一模一样的,不熟悉的可以看我之前的文章。传送门: Android 全面屏体验 那为什么还要写这篇文章呢?主要是在 Compose 中写法上的一些区别,…

4.26文件上传学习

文件上传,绕过,验证,检测一、文件上传 概念:(不赘述转web安全文件上传)[[9.6-9.7基础和过滤方式]] 前置知识:(除解析漏洞)后门代码需要以特定格式后缀解析,不能以图片后缀解析; 知识点 1、文件上传-前端验证 直接修改前端js代码,文件上传格式; 2、黑白名单 3、use…

Python-Flask-migrate安装和使用

在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库。最直接的方式就是删除旧表,但这样会丢失数据。 更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把变动应用到数据库中。在Flask中可以使用Flask-Migrate扩展,来实现数据迁移。 环境…

MySQL-07.InnoDB数据存储结构

C-07.InnoDB数据存储结构 1.数据库的存储结构:页索引结构给我们提供了高效的索引方式,不过索引信息以及数据记录都是保存在文件上的,确切说是存储在页结构中。另一方面,索引是在存储引擎中实现的,MySQL服务器上的存储引擎负责对表中数据的读取和写入工作。不同存储引擎中存…

以链表为基础实现链式队列——————遍历、入队、出队

以链表为基础实现链式队列 ​ 如果打算以链表作为基础来实现队列的操作,可以避免内存浪费以及避免内存成片移动,只需要确定队头和队尾即可,一般把链表头部作为队头,可以实现头删,把链表尾部作为队尾,可以实现尾插。​ 需要注意的点:遍历队列需要备份地址 出队需要考虑空…

Windows设置开机自启动项

一、常见软件的开机自启设置大部分安装的软件,在设置中都带有“设置开机自启”的选项,直接在软件本身的设置中勾选相应开关项即可。 二、本身无开机自启的软件或一些绿色便携式的软件 (一)实现原理Windows自带了一个启动文件夹,在此文件夹中的软件都会在开机后进行启动操作…

Unsortbin attack原理及分析

Unsortbin attack原理 ✔️条件:首先要实现Unsortbin attack前提是可以控制Unsortbin attack chunk的bk指针 ✔️目的:我们可以实现修改任意地址为一个比较大的值 ✔️原理:1.Unsortbin的来源 1.当一个较大的 chunk 被分割成两半后,如果剩下的部分大于MINSIZE,就会被放到 …