[蓝桥杯 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 题。
题解思路
本题的关键在于学习一个前缀和思想,否则,这道题的时间复杂度为 O ( n 2 ) O(n^2) O(n2) ,可能会存在超时情况。前缀和,顾名思义,对所给数组进行预处理,计算数组前面 i i i 项的和。
题目中所给式子为
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
将其提取公因式为
S = a 1 × ( a 2 + … + a n ) + a 2 × ( a 3 + … + a n ) + … + a n − 1 × a n S=a_{1}\times \left( a_{2}+\ldots +a_{n}\right) +a_{2}\times \left( a_{3}+\ldots +a_{n}\right) +\ldots +a_{n-1}\times a_{n} S=a1×(a2+…+an)+a2×(a3+…+an)+…+an−1×an
则此式被转变为从 a 1 . . . a n − 1 a_1 ... a_{n-1} a1...an−1 与其后面所有项之和的乘积,而这个所有项之和乘积,就是本题重点。代码中所列temp数组即为前缀和数组,其中 t e m p i temp_i tempi 为前 i i i 项和。而如果我们想知道原数组下标为 l l l ~ r r r 的和,那么直接通过式子 temp[r] - temp[l - 1] 即可;此处如果 l = 0 l=0 l=0 那么式子即 temp[r]。
题解代码
CPP代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int n;
scanf("%d", &n);
vector<int> nums(n);
for (register int i(0); i < n; ++i)
{
scanf("%d", &nums[i]);
}
vector<ll> temp(n);
temp[0] = nums[0];
for (register int i(1); i < n; ++i)
{
temp[i] = temp[i - 1] + nums[i];
}
ll res = 0;
for (register int i(0); i < n - 1; ++i)
{
res += nums[i] * (temp[n - 1] - temp[i]);
}
printf("%lld\n",res);
return 0;
}
Java代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; ++i) {
nums[i] = sc.nextInt();
}
long[] temp = new long[n];
temp[0] = nums[0];
for (int i = 1; i < n; ++i) {
temp[i] = temp[i - 1] + nums[i];
}
long res = 0;
for (int i = 0; i < n - 1; ++i) {
res += nums[i] * (temp[n - 1] - temp[i]);
}
System.out.println(res);
sc.close();
}
}