蓝桥杯2018年A组-付账问题
0.题目
题目描述
几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。
现在有
为了公平起见,我们希望在总付钱量恰好为
标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的“偏差有多大”。形式化地说,设第
输入格式
第一行包含两个整数
第二行包含
输出格式
输出到标准输出。
输出最小的标准差,四舍五入保留
保证正确答案在加上或减去
样例 #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
提示
【样例解释】
- 每个人都出 2333/5 元,标准差为 0。
【数据约定】
对于
对于
对于
对于
对于所有数据,
1.题解
1.1 贪心
思路
这里有很多需要注意的点:
1.这里我们首先明确一点:最终计算的avg是固定的,即 S / n
2.我们主要弄清一个问题:每个人付款有多有少,谁多谁少,如何让这个标准差最小
3.使用贪心的思路: 首先我们为了逼近avg:
3.0首先我们对于整个数组进行排序,便于后续使用贪心算法(这里sort排序,注意1.我a数组从下标1开始; 2.第二个参数是结束位置的下一个位置)
3.1如果存在有些钱不够的人(a[i] < avg),这些人两种选择:付全款/付部分; 如果他们付部分,他们自身首先和avg形成的标准差更大;其次对于后面有富裕的人,他们本来可
以用更接近avg的钱即可付完全款,但是由于你少付了,他们都要多付,跟avg的标准差也就更大;所以对于这部分人我们选择全部付款
3.2出现第二种人,有富裕,但不多(a[i] >= avg), 这些人能付的钱已经大于平均值,但是由于前面有人少付了钱,这时候我支付avg是不够的,需要他们进行多付.又回到了这
个问题,他们是全付还是付部分即可? 我们可以利用之前的遍历,更新剩余需支付的S,计算出新的平均值(总人数 n-i+1)avg', 对于剩余这部分的人,如果持钱最少的人都多
于avg',那么对于后面钱更多的人,也是能付起avg'的,而且这时候整体最逼近于avg(接近avg的都尽可能全付,直到出现一个符合的avg'),剩余部分的人只需要付avg'的钱款
即可.
4.这里判断 a[i] >= avg', 并不是写作 a[i] >= S' / (n - i + 1) 而是写作乘法,避免精度确实的问题!!!
5.注意最后所有人不是付款当前人持有的a[i], 而是均支付 avg' 即可, 由于持有钱款不是连续, 可能当前 a[i] > 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了