蓝桥杯|[蓝桥杯] 付账问题
付账问题
题目
几个人一起出去吃饭是常有的事。
但在结帐的时候,常常会出现一些争执。
现在有 n 个人出去吃饭,他们总共消费了 S 元。
其中第 i 个人带了 ai 元。
幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?
为了公平起见,我们希望在总付钱量恰好为 S 的前提下,最后每个人付的钱的标准差最小。
这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是 1 分钱的整数倍。
【蓝桥杯|[蓝桥杯] 付账问题】你需要输出最小的标准差是多少。
标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的“偏差有多大”。
形式化地说,设第 i 个人付的钱为 bi 元,那么标准差为 :
文章图片
输入格式
第一行包含两个整数 n、S;
第二行包含 n 个非负整数 a1,?…,?an。
输出格式
输出最小的标准差,四舍五入保留 4 位小数。
数据范围
1 ≤ n ≤ 5 × 105 0 ≤ a i , S ≤ 109 1≤n≤5×105 \\ 0≤ai,S≤109 1≤n≤5×1050≤ai,S≤109
输入样例
10 30输出样例
2 1 4 7 4 8 3 6 4 7
0.7928题解 思路
- 首先算出平均值 s/n,把数据从小到大排序
- 如果某个人的钱低于该值,那么他将钱全部支付,然后其余不够的其他人平摊
#include
#include
#include using namespace std;
const int N = 5 * 1e5 + 20;
int n;
double a[N], b[N], S;
int main () {
cin >> n >> S;
for (int i = 0;
i < n;
i ++) cin >> a[i];
sort(a, a + n);
double avg = (double)S / n;
int start = 0;
while (S > 0) {
for (int i = start;
i < n;
i ++) {
if (a[i] <= avg) {
b[i] += a[i], S -= a[i], a[i] = 0;
start = i + 1;
}
else {
b[i] += avg, S -= avg, a[i] -= avg;
}
}
avg = S / (n - start);
}double sum = 0;
for (int i = 0;
i < n;
i ++) sum += b[i];
avg = sum / n, sum = 0;
for (int i = 0;
i < n;
i ++) sum += (b[i] - avg) * (b[i] - avg);
printf("%.4lf", sqrt(sum / n));
return 0;
}
题解二
- 来源:AcWing 1235. 付账问题
#include
#include
#include
#include
#include using namespace std;
const int N = 500010;
int n;
int a[N];
int main()
{
double s;
scanf("%d%lf", &n, &s);
for (int i = 0;
i < n;
i ++ ) scanf("%d", &a[i]);
sort(a, a + n);
double res = 0, avg = s / n;
for (int i = 0;
i < n;
i ++ )
{
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;
}
推荐阅读
- 热闹中的孤独
- 诗歌:|诗歌: 《让我们举起世界杯,干了!》
- 年轻人,干了孤独这杯酒
- 不以胜负论出关
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- 蓝桥杯试题
- python青少年编程比赛_第十一届蓝桥杯大赛青少年创意编程组比赛细则
- 临清一中学子斩获北大培文杯作文大赛全国大奖
- 第三届文人杯诗书画大赛获名单公示
- 会爆炸的『巧克力棉花糖球』,这样一杯甜品真的太有想法了!