题目出处:蓝桥杯2022初赛
题目描述
给定n个整数a[1],a[2],…,a[n],求两两相乘再相加的和,即
S=a[1]·a[2]+a[1]·a[3]+…+a[1]·a[n]+a[2]·a[3]+…+a[2]·a[n]+…+a[n-1]·a[n]
输入格式
第一行为正整数n,第二行为n个整数。
30%的数据:2≤n≤1000,1≤a[i]≤100。
100%的数据:2≤n≤200000,1≤a[i]≤1000。
输出格式
输出一个数字表示答案S。
输入样例
4
1 3 6 9
输出样例
117
问题分析
用暴力法来解题会超时,参见最后一个代码。
一种解法是使用前缀和来计算,连存储数据的数组也不需要。
另外一种解法是根据公式来计算,其要点如下:
给定n个数,求部分两两相乘问题,需要找出其规律来,算起来就简单了。
先求出n个整数之和,再求出这n个整数的平方和,然后用公式算一下就好了。
具体的计算方法见程序代码。
求和后数会变得比较大,所以要用long long类型。
AC的解题代码(前缀和)如下:
/* LQ0014 求和 */
#include
int main()
{
int n, a;
long long sum = 0, psum = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a);
sum += psum * a;
psum += a;
}
printf("%lld\n", sum);
return 0;
}
AC的解题代码(公式)如下:
/* LQ0014 求和 */
#include
int main()
{
int n, a;
long long sum = 0, sum1 = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a);
sum += a;
sum1 += a * a;
}
printf("%lld\n", (sum * sum - sum1) / 2);
return 0;
}
超时的解题代码(暴力)如下:
/* LQ0014 求和 */
#include
#define N 200000
int a[N];
int main()
{
int n;
long long sum = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
sum += a[i] * a[j];
printf("%lld\n", sum);
return 0;
}