题目相关
题目链接
AtCoder Beginner Contest 177 C 题,https://atcoder.jp/contests/abc177/tasks/abc177_c。
Problem Statement
Given are N integers A1, …, AN.
Find the sum of Ai×Aj over all pairs (i,j) such that 1 ≤ i < j ≤ N, modulo (10^9+7).
Input
Input is given from Standard Input in the following format:
N
A1 … AN
Output
Print . modulo ().
Samples1
Sample Input 1
3
1 2 3
Sample Output 1
11
Explaination
We have 1×2+1×3+2×3=11.
Samples2
Sample Input 2
4
141421356 17320508 22360679 244949
Sample Output 2
437235829
Constraints
- 2 ≤ N ≤ 2×10^5
- 0 ≤ Ai ≤ 10^9
- All values in input are integers.
题解报告
题目翻译
给 N 个整数 A1, A2, ..., An,求 Ai*Aj 的总和,其中 1 ≤ i < j ≤ N,由于这个值会很大,对 10^9+7 取模。
题目分析
本题的核心就是计算公式:。由于 N 的范围是 2 ≤ N ≤ 2×10^5,我们知道,直接使用双重循环来计算,肯定是一个 TLE 的结果。
for (int i=1; i<=n-1; i++) {
for (int j=i+1; j<=n; j++) {
ans += a[i]*a[j];
}
}
因为使用双重循环的时间复杂度为 O(N^2),对于 2e5 的数据,这点时间肯定是不够的,因此我们需要做的是对算法进行优化,将算法的时间复杂度降低为 O(N)。
我们可以直接将计算公式展开得到如下:
这样 看上去是不是很眼熟,不错,就是前缀和。也就是,我们可以通过前缀和这个预处理,来降低算法的复杂度,这样,我们通过数学将 O(N^2) 的时间复杂度,降低到了 O(N)。
这样本题我们就可以通过了。
由于数据比较大,需要进行取模,那么就需要用到数论中的取模定理。
AC 参考代码
//177 c 求乘积之和
#include <bits/stdc++.h>
using namespace std;
const int MAX=2e5+6;
long long sl[MAX],sz[MAX];
int main(){
int n;
cin>>n;
for (int i=1;i<=n;i++) {
cin>>sl[i];
sz[i]=(sz[i-1]+sl[i]);
}
long long ans=0;
for (int j=1;j<=n;j++) {
ans+=(sl[j]%1000000007)*((sz[n]-sz[j])%1000000007);
ans%=1000000007;
}
cout<<ans<<endl;
return 0;
}