题目描述
给定 n 个整数 a 1 , a 2 , ⋅ ⋅ ⋅ , a n a_1,a_2,···,a_n a1,a2,⋅⋅⋅,an,求它们两两相乘再相加的和,即
S = a 1 ⋅ a 2 + a 1 ⋅ a 3 + ⋅ ⋅ ⋅ + a 1 ⋅ a n + a 2 ⋅ a 3 + ⋅ ⋅ ⋅ + a n − 2 ⋅ a n − 1 + a n − 2 ⋅ a n + a n − 1 ⋅ a n S=a_1⋅a_2+a_1⋅a_3+⋅⋅⋅+a_1⋅a_n+a_2⋅a_3+⋅⋅⋅+a_{n−2}⋅a_{n−1}+a_{n−2}⋅a_n+a_{n−1}⋅a_n S=a1⋅a2+a1⋅a3+⋅⋅⋅+a1⋅an+a2⋅a3+⋅⋅⋅+an−2⋅an−1+an−2⋅an+an−1⋅an
输入格式
输入的第一行包含一个整数 n。
第二行包含 n 个整数 a 1 , a 2 , ⋅ ⋅ ⋅ , a n a_1,a_2,···,a_n a1,a2,⋅⋅⋅,an。
输出格式
输出一个整数 S,表示所求的和。
请使用合适的数据类型进行运算。
数据范围
对于 30%的数据,
1
≤
n
≤
1000
,
1
≤
a
i
≤
100
1≤n≤1000,1≤a_i≤100
1≤n≤1000,1≤ai≤100。
对于所有评测用例,
1
≤
n
≤
200000
,
1
≤
a
i
≤
1000
1≤n≤200000,1≤a_i≤1000
1≤n≤200000,1≤ai≤1000。
输入样例:
4
1 3 6 9
输出样例:
117
时/空限制:1s/256MB
暴力解法:
两重循环遍历数组,但只能过30%的数据,剩下的会超时。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 200020;
LL a[N], s[N], sum;
int n;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++)
{
for(int j = i+1; j <= n; j++) sum += a[i] * a[j];
}
cout << sum;
return 0;
}
前缀和:
化简一下求和公式,对于每一项: a 1 ( a 2 + a 3 + a 4 ) , a 2 ( a 3 + a 4 ) , a 3 ⋅ a 4 a_1(a_2+a_3+a_4), a_2(a_3+a_4), a_3·a_4 a1(a2+a3+a4),a2(a3+a4),a3⋅a4。
括号里面可用前缀和计算,算出前 n n n 项的和减去前 i i i 项的和,再乘以第 i i i 项,累加起来即可。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 200020;
LL a[N], s[N];//a[N]存每一项,s[N]存前i项和:s[1]为前1项和,s[2]为前两项和...
int n;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
//预处理,求前i项和
for(int i = 1; i <= n; i++)
{
s[i] = s[i-1] + a[i];
}
LL ans = 0;
for(int i = 1; i <= n; i++)
{
ans += a[i] * (s[n] - s[i]);
}
cout << ans;
return 0;
}