51Nod - 1098 最小方差

Posted zhang--yd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51Nod - 1098 最小方差相关的知识,希望对你有一定的参考价值。

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

 

题解: 

    求 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; 
}

  

 

以上是关于51Nod - 1098 最小方差的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1098 最小方差 排序+前缀和+期望方差公式

1098 最小方差 (数论)

求最小原根 51nod 1135

51nod 1012 最小公倍数LCM

51 nod 1097 拼成最小的数 思路:字符串排序

51nod 1616 最小集合