• 51nod 最小方差


    1098 最小方差

    若x1,x2,x3......xn的平均数为k。
    则方差s^2 = 1/n * [(x1-k)^2+(x2-k)^2+.......+(xn-k)^2] 。
    方差即偏离平方的均值,称为标准差或均方差,方差描述波动程度。
    给出M个数,从中找出N个数,使这N个数方差最小。
     
    Input
    第1行:2个数M,N,(M > N, M <= 10000)
    第2 - M + 1行:M个数的具体值(0 <= Xi <= 10000)
    Output
    输出最小方差 * N的整数部分。
    Input示例
    5 3
    1
    2
    3
    4
    5
    Output示例
    2

    先排序,计算前n个的方差。然后[1,n+1]之间的方差可以在[1,n]的基础上得到。

    设k为(a1+a2+...+an)/n  s2 = [(a1-k)2+(a2-k)2+...+(an-k)2]   就不除以n了,因为答案要乘以n

    现在计算[1,n+1]的方差,现在的平均数变成了k + (an+1-a1)/n 

    设(an+1-a1)/n 为x ,即s2' =  [(a2-k-x)2+(a3-k-x)2+...+(an+1-k-x)2

    展开为s2' = [(an+1-k-x)2 + (a2-k)2 - 2x(a2-k)2 - 2x(a3-k)2 - ... - 2x(an-k)2+(n-1)x2)]

    s2' - s2 = (an+1-k-x)2 - (a1-k)2 + 2x(a1-k) + (n-1)x2

    所以后面的方差可以根据前面的得到,复制度就是O(nlogn)了,主要是排序占时间,只要扫描一遍。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e4+10;
     4 int a[N];
     5 int main() {
     6     int n, m;
     7     cin >> m >> n;
     8     for(int i = 0; i < m; i ++) cin >> a[i];
     9     sort(a, a+m);
    10     double s = 0, sum = 0;
    11     for(int i = 0; i < n; i ++) sum += a[i];
    12     double k = sum/n;
    13     for(int i = 0; i < n; i ++) {
    14         s += 1.0*(a[i]-sum/n)*(a[i]-sum/n);
    15     }
    16     double ss = s;
    17     for(int i = n; i < m; i ++) {
    18         double x = 1.0*(a[i]-a[i-n])/n;
    19         s = s + (a[i]-k-x)*(a[i]-k-x)-(a[i-n]-k)*(a[i-n]-k)+2*x*(a[i-n]-k)+x*x*(n-1);
    20         ss = min(ss,s);
    21         k = x+k;
    22     }
    23     printf("%.0f
    ",floor(ss));
    24     return 0;
    25 }
  • 相关阅读:
    StackView
    横竖屏
    Html
    UILabel
    NSString
    NSPredicate|谓词
    iphone
    函数
    UIBezierPath
    UICollectionView
  • 原文地址:https://www.cnblogs.com/xingkongyihao/p/8933586.html
Copyright © 2020-2023  润新知