我们把方差公式进行化简。记
s
u
m
1
sum_1
sum1 为每个数的前缀和,
s
u
m
2
sum_2
sum2 为每个数平方后的前缀和
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}
m1i=1∑m(bi−b)2=m1i=1∑m(bi2−2∗bi∗b+b2)=m1(sum2−2∗b∗sum1+m∗b2)=m1(sum2−2∗msum12+msum12)=msum2−m2sum12
于是我们要求的答案为
(
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
(n−1)∗(sum2−ai2)−(sum1−ai)2
O
(
n
)
O(n)
O(n) 求出前缀和后每一步可以
O
(
1
)
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;
}
总结
主考公式化简