有一天Miss Quan出了一个题,给出一个长度为的数组
Miss Quan说给我计算下这个权值等于多少,然后随手写了一个式子,把她的小伙伴们都给惊呆了,这是什么鬼…
比如
N
=
2
,
V
a
l
u
e
=
(
a
2
−
a
1
)
2
+
(
a
3
−
a
1
)
2
+
(
a
3
−
a
2
)
2
N=2,Value=(a_2-a_1)^2+(a_3-a_1)^2+(a_3-a_2)^2
N=2,Value=(a2−a1)2+(a3−a1)2+(a3−a2)2
听到这里,小伙伴们说这不是很简单吗,于是写出了下面的代码:
Miss Quan会心一笑,大家意识到事情并不简单,这个解法时间复杂度太高了,你能想出更好的计算Value的方法吗?只需要输出Value的值即可。
输入描述
第一行输入一个整数代表共有
T
T
T组数据
T
(
1
≤
T
≤
50
)
T(1\leq T\leq 50)
T(1≤T≤50)。
对于每组测试用例第一行输入一个整数
n
(
2
≤
n
≤
50000
)
n(2\leq n \leq 50000)
n(2≤n≤50000)第二行输入
n
n
n个数
a
1
,
a
2
,
a
3
,
…
,
a
n
(
1
≤
a
i
≤
1
0
4
)
a_1,a_2,a_3,\dots,a_n(1\leq a_i \leq 10^4)
a1,a2,a3,…,an(1≤ai≤104)
输出描述
对于每组数据,输出一行,一个整数 V a l u e Value Value代表的值.
示例1
输入
2
3
1 4 2
2
10 20
输出
14
100
示例2
输入
1
4
5 6 8 7
输出
20
Solve
通过对上述公式化简,可以得到:
V
a
l
u
e
=
(
n
−
1
)
×
∑
i
=
1
n
a
i
2
−
2
×
(
∑
i
=
1
n
−
1
(
a
i
×
∑
j
=
i
+
1
n
a
j
)
)
Value=(n-1)\times \sum_{i=1}^{n} a_{i}^{2}-2\times (\sum_{i=1}^{n-1}(a_i\times \sum_{j=i+1}^{n}a_j))
Value=(n−1)×i=1∑nai2−2×(i=1∑n−1(ai×j=i+1∑naj))
然后用前缀和处理一下
∑
j
=
i
+
1
n
a
j
\sum_{j=i+1}^{n}a_j
∑j=i+1naj的值,可以得到最终公式:
V
a
l
u
e
=
(
n
−
1
)
×
∑
i
=
1
n
a
i
2
−
2
×
(
∑
i
=
1
n
−
1
a
i
×
s
u
m
n
−
s
u
m
i
)
Value=(n-1)\times \sum_{i=1}^{n} a_{i}^{2}-2\times (\sum_{i=1}^{n-1}a_i\times sum_n-sum_i)
Value=(n−1)×i=1∑nai2−2×(i=1∑n−1ai×sumn−sumi)
Code
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
#define INF 0x7f7f7f7f
const int maxn=1e6+10;
const int mod=1e9+7;
using namespace std;
ll a[maxn];
ll sum[maxn];
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
ms(sum,0);
int n;
cin>>n;
ll value=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
value+=(n-1)*a[i]*a[i];
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<n;i++)
value-=2*a[i]*(sum[n]-sum[i]);
cout<<value<<endl;
}
return 0;
}