1. 程式人生 > >【題解】[牛客網NOIP賽前集訓營-提高組(第二場)]A.方差 字首和

【題解】[牛客網NOIP賽前集訓營-提高組(第二場)]A.方差 字首和

題目連結
在這裡插入圖片描述
在這裡插入圖片描述


我們把方差公式進行化簡。記 s u m 1 sum_1 為每個數的字首和, s

u m 2 sum_2 為每個數平方後的字首和
1 m
i = 1 m ( b i
b ) 2 = 1 m i = 1 m ( b i 2 2 b i b + b 2 ) = 1 m ( s u m 2 2 b s u m 1 + m b 2 ) = 1 m ( s u m 2 2 s u m 1 2 m + s u m 1 2 m ) = s u m 2 m s u m 1 2 m 2 \frac{1}{m}\sum_{i=1}^m(b_i-\overline{b})^2\\=\frac{1}{m}\sum_{i=1}^m(b_i^2-2*b_i*\overline{b}+\overline{b}^2)\\=\frac{1}{m}(sum_2-2*\overline{b}*sum_1+m*\overline{b}^2)\\=\frac{1}{m}(sum_2-2*\frac{sum_1^2}{m}+\frac{sum_1^2}{m})\\=\frac{sum_2}{m}-\frac{sum_1^2}{m^2}

於是我們要求的答案為
( n 1 ) ( s u m 2 a i 2 ) ( s u m 1 a i ) 2 (n-1)*(sum_2-a_i^2)-(sum_1-a_i)^2
O ( n ) O(n) 求出字首和後每一步可以 O ( 1 ) O(1) 求出解

#include<cstdio>
typedef long long ll;
const int N=1e5+10;
int n,a[N];
ll sum2,sum1;
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	    scanf("%d",&a[i]),sum1+=a[i],sum2+=a[i]*a[i];
	for(int i=1;i<=n;i++)
	    printf("%lld ",(n-1)*(sum2-a[i]*a[i])-(sum1-a[i])*(sum1-a[i]));
	return 0;
}

總結

主考公式化簡