51Nod - 1098 最小方差
51Nod - 1098 最小方差
若x1,x2,x3......xn的平均数为k。
则方差s^2 = 1/n * [(x1-k)^2+(x2-k)^2+.......+(xn-k)^2] 。
方差即偏离平方的均值,称为标准差或均方差,方差描述波动程度。
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
题解:
求 x(i+1) + x(i+2) + ... + x(i+2) 的平方差,
(x[i+1] - avg)^2 + (x[i+2] - avg)^2 + ... + (x[i+n] - avg)^2 = (x[i+1] ^ 2 + x[i+2]^2 + .. + x[i+n]^2 - 2*avg*(x[i+1] + ... + x[i+n]) + n*avg*avg )
根据这个可以将时间由O(n*m) 缩小到O(n)
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 10000 + 10;
int n, m, num[MAXN], pow2[MAXN];
int cmp(const void *a, const void *b){
return (*(int *)a - *(int *)b);
}
int main(){
long long ans, sum_power, sum_num, tmp;
double avg;
while(scanf("%d %d", &m, &n) != EOF){
for(int i=0; i<m; ++i){
scanf("%d", &num[i]);
}
qsort(num, m, sizeof(num[0]), cmp);
for(int i=0; i<m; ++i){
pow2[i] = num[i] * num[i];
}
sum_num = 0;
sum_power = 0;
for(int i=0; i<n; ++i){
sum_num += num[i];
sum_power += pow2[i];
}
avg = sum_num *1.0 / n;
ans = (long long)(sum_power - 2*avg*sum_num + n*avg*avg);
for(int i=n; i<m; ++i){
sum_num += num[i] - num[i-n];
sum_power += pow2[i] - pow2[i-n];
avg = sum_num *1.0 / n;
tmp = (long long)(sum_power - 2*avg*sum_num + n*avg*avg);
if(tmp < ans){
ans = tmp;
}
}
printf("%lld\n", ans );
}
return 0;
}

浙公网安备 33010602011771号