这题本不想写题解的,因为是极水的一道公式题
题目链接:方差
题目:
题意
一个长度为 m 的序列 b[1…m] ,我们定义它的方差为 ,其中
表示序列的平均值。
可以证明的是,如果序列元素均为整数,那么方差乘以 m^2 之后,得到的值一定是整数。
现在有一个长度为 N 的序列 a[1…N],对每个 i = 1~N,你需要计算,如果我们删除 a[i],剩下的 N-1 个元素的方差乘以 (N-1)^2 的值。
输入描述:
第一行一个整数 N。
接下来一行 N 个整数,第 i 个数表示 a[i]。
输出描述:
一行 N 个整数,第 i 个数表示删掉 a[i] 后,剩下元素的方差乘以 (N-1)^2 的值。
题解:
把
∑nj=1aj
∑
j
=
1
n
a
j
记为s,
∑nj=1a2j
∑
j
=
1
n
a
j
2
记为q
去掉a[k]的方差乘以(n-1)^2的值可表示为
∑ni=1(ai(m−1)−s+ak)2−(akm−s)2n−1
∑
i
=
1
n
(
a
i
(
m
−
1
)
−
s
+
a
k
)
2
−
(
a
k
m
−
s
)
2
n
−
1
展开化简得
(n−1)q−s2+2bks−nb2k
(
n
−
1
)
q
−
s
2
+
2
b
k
s
−
n
b
k
2
s,q预处理出来,每个询问都是
O(1)
O
(
1
)
,总时间复杂度
O(n)
O
(
n
)
,空间
O(n)
O
(
n
)
代码:
#include <iostream>
#include <stdio.h>
using namespace std;
const int N=1e5+5;
long long n,Ab,ASb,ai[N],bi[N];
long long cal(int k){
return (n-1ll)*ASb-Ab*Ab+2ll*bi[k]*Ab-n*bi[k]*bi[k];
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>bi[i];
Ab+=bi[i];
ASb+=bi[i]*bi[i];
}
cout<<cal(1);
for(int k=2;k<=n;k++)
cout<<" "<<cal(k);
cout<<endl;
return 0;
}