P8772 [蓝桥杯 2022 省 A] 求和
题目描述
给定 n n n 个整数 a 1 , a 2 , ⋯ , a n a_{1}, a_{2}, \cdots, 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
输入格式
输入的第一行包含一个整数 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,表示所求的和。请使用合适的数据类型进行运算。
样例 #1
样例输入 #1
4
1 3 6 9
样例输出 #1
117
提示
对于 30 % 30 \% 30% 的数据, 1 ≤ n ≤ 1000 , 1 ≤ a i ≤ 100 1 \leq n \leq 1000,1 \leq a_{i} \leq 100 1≤n≤1000,1≤ai≤100 。
对于所有评测用例, 1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ a i ≤ 1000 1 \leq n \leq 2\times10^5,1 \leq a_{i} \leq 1000 1≤n≤2×105,1≤ai≤1000 。
蓝桥杯 2022 省赛 A 组 C 题。
解题思路1:
根据题目问题的描述,可以对数组a[ ]的每一项进行一一枚举,执行两次循环直接暴力求出sum。
问题在于:
- 样例的范围最大为 2 × 1 0 5 2 \times10^5 2×105,暴力法时间复杂度为O( n 2 n^{2} n2),并不能AC,只能过部分样例
思路1C++代码如下:(暴力枚举 30’)
#include<iostream>
using namespace std;
const int N=2e5+10;
int a[N];
long long sum=0;
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n-1;i++)
{
for(int j=i+1;j<=n;j++) {
sum+=a[i]*a[j];
}
}
cout<<sum;
}
解题思路2:利用前缀和
可以把S变形一下:
S
=
a
1
⋅
∑
i
=
2
n
a
i
+
a
2
⋅
∑
i
=
3
n
a
i
+
…
+
a
n
−
2
⋅
∑
i
=
n
−
1
n
a
i
+
a
n
−
1
⋅
a
n
S=a_{1}\cdot\sum\limits_{i=2}^{n} a_{i} +a_{2}\cdot\sum\limits_{i=3}^{n} a_{i} +\ldots+ a_{n-2}\cdot\sum\limits_{i=n-1}^{n} a_{i} +a_{n-1}\cdot a_{n}
S=a1⋅i=2∑nai+a2⋅i=3∑nai+…+an−2⋅i=n−1∑nai+an−1⋅an
可以轻松的看出各部分相似部分为:
∑
i
=
k
n
a
i
\sum\limits_{i=k}^{n} a_{i}
i=k∑nai
于是便联想到前缀和这一算法思想,进一步的得出前缀和:
S
k
=
∑
i
=
1
k
a
i
S_k=\sum\limits_{i=1}^{k} a_{i}
Sk=i=1∑kai,可知晓:
∑
i
=
k
q
a
i
=
S
q
−
S
k
−
1
\sum\limits_{i=k}^{q} a_{i}=S_q-S_{k-1}
i=k∑qai=Sq−Sk−1
所以可以最终推导出:
S = ∑ i = 1 n − 1 ( a i ⋅ ( S n − S i ) ) S=\sum\limits_{i=1}^{n-1}( a_{i}\cdot(S_n-S_i)) S=i=1∑n−1(ai⋅(Sn−Si))
AC代码奉上:
#include<iostream>
using namespace std;
const int N=2e5+10;
int a[N];
long long sum[N];
long long s=0;
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=a[i]+sum[i-1];
}
for(int i=1;i<=n-1;i++)
{
s+=a[i]*(sum[n]-sum[i]);
}
cout<<s;
}