【题目描述】
几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。
现在有 n 个人出去吃饭,他们总共消费了 S 元。其中第 i 个人带了 a i 元。幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?
为了公平起见,我们希望在总付钱量恰好为 S 的前提下,最后每个人付的钱的标准差最小。这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是 1分钱的整数倍。你需要输出最小的标准差是多少。
标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的“偏差有多大”。形式化地说,设第 i 个人付的钱为 b i 元,那么标准差为
2
【输入格式】
从文件 eatout.in 中读入数据。
第一行包含两个整数 n、S;
第二行包含 n 个非负整数 a 1 ,...,a n 。
【输出格式】
输出到文件 eatout.out 中。
输出最小的标准差,四舍五入保留 4 位小数。保证正确答案在加上或减去 10 −9 后
不会导致四舍五入的结果发生变化。
【样例 1 输入】
5 2333
666 666 666 666 666
【样例 1 输出】
0.0000
【样例 1 解释】
每个人都出
2333
5
元,标准差为 0。
第 5 页 共 6 页
NOIP 模拟题 第 12 套 付账(eatout)
【样例 2 输入】
10 30
2 1 4 7 4 8 3 6 4 7
【样例 2 输出】
0.7928
【子任务】
对于 10% 的数据,所有 a i 相等;
对于 30% 的数据,所有非 0 的 a i 相等;
对于 60% 的数据,n ≤ 1,000;
对于 80% 的数据,n ≤ 10 5 ;
对于所有数据,n ≤ 5 × 10 5 ,0 ≤ a i ≤ 10 9 。
考试T3,挂了两个点,伤心QAQ
原因是我脑残的并且手残的自己写了四舍五入
但是写错了(我就是个SB)
我们可以得出平均数
然后对于钱不够的,我们让后面钱多的替他补上,同事计算方差
下面给出代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> using namespace std; inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } inline void write(int x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); return ; } int n; long double ans=0; long double m; long double a[1000006]; int main(){ n=rd(); scanf("%Lf",&m); for(int i=1;i<=n;i++) scanf("%Lf",&a[i]); sort(a+1,a+n+1); long double evr=m/(long double)n; long double num=0; for(int i=1;i<=n;i++){ if(a[i]<evr){ ans+=(a[i]-evr)*(a[i]-evr); num+=(evr-a[i]); } if(a[i]>evr){ long double x=num/(long double)(n-i+1); if(a[i]<evr+x){ ans+=(a[i]-evr)*(a[i]-evr); num-=(a[i]-evr); } if(a[i]>=evr+x){ ans+=x*x; num-=x; } } } long double f=sqrt(ans/(long double)n); long long x=(f/0.00001); if(x%10>=5) printf("%.4Lf",f+0.0001); else printf("%.4Lf",f); return 0; }