给定 n n 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} \cdot a_{2}+a_{1} \cdot a_{3}+\cdots+a_{1} \cdot a_{n}+a_{2} \cdot a_{3}+\cdots+a_{n-2} \cdot a_{n-1}+a_{n-2} \cdot a_{n}+a_{n-1} \cdot a_{n} S=a1⋅a2+a1⋅a3+⋯+a1⋅an+a2⋅a3+⋯+an−2⋅an−1+an−2⋅an+an−1⋅an
输入的第一行包含一个整数 nn。
第二行包含 n n n 个整数 a 1 , a 2 , ⋯ , a n a_1,a_2,\cdots, a_n a1,a2,⋯,an 。
输入的第一行包含一个整数 n n n。
第二行包含 n n n 个整数 a 1 , a 2 , ⋯ , a n a_1,a_2,\cdots, a_n a1,a2,⋯,an
输出一个整数 S S S,表示所求的和。请使用合适的数据类型进行运算。
4
1 3 6 9
117
1 ≤ n ≤ 200000 , 1 ≤ a i ≤ 1000 1 \leq n \leq 200000,1 \leq a_{i} \leq 1000 1≤n≤200000,1≤ai≤1000
link
如果暴力获取答案的复杂度将会是 O ( n 2 ) O(n^2) O(n2)级别,会超时。仔细不难发现,对于任意一个 a i a_i ai,它只会主动和下标比它大的数相乘。即我们可以提公因式子: a i ⋅ a i + 1 + a i ⋅ a i + 2 + . . . . . . + a i ⋅ a n = ( a i + 1 + a i + 2 + . . . . . . + a n ) a_i \cdot a_{i+1}+a_{i} \cdot a_{i+2}+......+a_i \cdot a_n=(a_{i+1}+a_{i+2}+......+a_{n}) ai⋅ai+1+ai⋅ai+2+......+ai⋅an=(ai+1+ai+2+......+an)
对于右边式子不难发现可以利用前缀和在 O ( 1 ) O(1) O(1)时间内求出,即预处理前缀和数组后我们可以在 O ( n ) O(n) O(n)的时间复杂度内得到答案。
#include
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> PII;
#define pb(s) push_back(s);
#define SZ(s) ((int)s.size());
#define ms(s,x) memset(s, x, sizeof(s))
#define all(s) s.begin(),s.end()
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const int N = 200010;
int n;
LL a[N];
LL s[N];
void solve()
{
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
LL ans = 0;
for (int i = 1; i <= n; ++i) {
ans += s[i - 1] * a[i];
}
cout << ans << '\n';
}
int main()
{
ios_base :: sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
while (t--)
{
solve();
}
return 0;
}