题目描述
几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。
现在有 �n 个人出去吃饭,他们总共消费了 �S 元。其中第 �i 个人带了 ��ai元。幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?
为了公平起见,我们希望在总付钱量恰好为 �S 的前提下,最后每个人付的钱的标准差最小。这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是 1 分钱的整数倍。你需要输出最小的标准差是多少。
标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的"偏差有多大"。形式化地说,设第 �i 个人付的钱为 ��bi 元,那么标准差为 :
�=1�∑�=1�(��−1�∑�=1���)2S=n1∑i=1n(bi−n1∑i=1nbi)2
输入描述
第一行包含两个整数 �、�n、S;
第二行包含 �n 个非负整数 �1, ⋯, ��a1, ⋯, an。
其中,�≤5×105,0≤��≤109n≤5×105,0≤ai≤109 。
输出描述
输出最小的标准差,四舍五入保留 4 位小数。
保证正确答案在加上或减去 10−910−9 后不会导致四舍五入的结果发生变化。
输入输出样例
示例
输入
5 2333
666 666 666 666 666
输出
0.0000
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
解题思路
按财力从小到大排序,实时更新的还需支付的钱,通过时时更新的平均支付值来贪心
代码
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define LL long long
#define MAX(A, B) (((A) > (B))? (A): (B))
double a[500005];
int cmp(const void* p, const void* q);
int main(int argc, char* argv[]) {
double n, S;
int i;
double ave = 0, ans = 0, avg;
scanf(" %lf %lf", &n, &S);
for (i = 0; i < n; i++) scanf("%lf", &a[i]);
ave = S / n;
qsort(a, n, sizeof(a[0]), cmp);
for (i = 0; i < n; i++) {
if(a[i] * (n - i) < S) {
ans += (ave - a[i]) * (ave - a[i]);
S -= a[i];
}
else {
avg = S / (n - i);
ans += (avg - ave) * (avg - ave) * (n - i);
break;
}
}
ans = sqrt(ans / n);
printf("%.4f\n", ans);
return 0;
}
int cmp(const void* p, const void* q) {
double* a = (double*)p;
double* b = (double*)q;
if (*a > *b) return 1;
else return -1;
}