问题 G: 方差 普拉斯
时间限制: 1 Sec 内存限制: 128 MB提交: 94 解决: 17
[提交] [状态] [讨论版] [命题人:admin]
题目描述 方差(样本方差)是每个样本值与全体样本值的平均数之差的平方值的平均数。在许多实际问题中,研究方差即偏离程度有着重要意义。 若x1,x2,x3......xn的平均数为k,则方差s^2 = 1/n * [(x1-k)^2+(x2-k)^2+.......+(xn-k)^2] 。 给出M个数,从中找出N个数,使这N个数方差最小。 输入 第1行:2个数M,N,(M > N, M <= 10000) 第2 - M + 1行:M个数的具体值(0 <= Xi <= 10000) 输出 输出最小方差 * N的整数部分。 样例输入 5 3 1 2 3 4 5 样例输出 2
大致思路:
1、求方差,暴力即可!暴力下来也只有两重for循环!不会超时!
2、设下标从x1--x2的n个数的方差为s1,平均数k1,下标x1+1—x2+1 的方差为s2,平均数为k2, 前后两者有一点联系,就是平均数会涉及到一些重复计算,分别设为k1和k2,k2=k1-x1/n+(x2+1)/n,省去了一些计算复杂度!但是,方差s1和s2并不能直接像类似于k1和k2那样直接转化!那么s2需要老老实实地再计算一遍!(我看着样例,直接得出了s1得到s2的式子!WA了一次!)因此时间复杂度不会因为一点k1得到k2的优化而发生变化!毕竟乘法时间复杂更大!
3、记得这个样本序列需要进行排序,升序排序一遍即可!不排序我WA了!
4、别被题面吓住了!尤其是开篇的两道题目造成的深深的心理阴影,后面的题目其实才简单呢!!!多做题,才能克服自己内心深处的恐惧!
5、会不会超double类型呢!貌似不会!假设(x1-k)等于1e4,那么平方会就是1e8,并且还有N个数,那个总的和就是1e12次方,基本会超过double了!不放心的话,可以在求xi的时候把(xi-k)*(xi-k)/N 调整成 (xi-k)/N*(xi-k),这样就肯定没问题了。
题解:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<string> 5 #include<vector> 6 #include<algorithm> 7 #define ll long long 8 using namespace std; 9 #define N 10000 10 #define ll long long 11 double a[N+10]; 12 13 int main() 14 { 15 int m,n; 16 while(scanf("%d%d",&m,&n)!=EOF){ 17 for(int i=1;i<=m;i++) 18 scanf("%lf",&a[i]); 19 sort(a+1,a+1+m); 20 // for(int i=1;i<=m;i++) 21 // printf("*%lf ",a[i]); 22 23 a[0]=0; 24 double sum=0,k=0,s2=0,ans=999999999.9; 25 for(int i=1;i<n;i++) 26 sum+=a[i]; 27 for(int i=n;i<=m;i++){ 28 sum=sum+a[i]-a[i-n]; 29 k=sum/n; 30 s2=0; 31 for(int j=i;j>=i-n+1;j--) 32 s2=s2+(a[j]-k)/(1.0*n)*(a[j]-k); 33 ans=min(ans,s2); 34 } 35 36 printf("%lld ",(ll)(ans*1.0*n+1e-8)); 37 38 } 39 40 41 return 0; 42 }