题目
链接:蓝桥杯2022年第十三届省赛真题-求和 - C语言网 (dotcpp.com)
输入输出以及样例格式
首先来看看传统的思想
#include<stdio.h>
int main()
{
int n = 0;
long long sum = 0;//由于和的大小测试样例肯定有超过int的最大范围,这里用long long
scanf("%d", &n);//输入数字个数
int arr[n];//这里使用了变长数组,vs上跑不过去,但这里可以
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);//循环输入n个数,并将其存入arr数组里面
}
for (int i = 0; i < n - 1; i++)//遍历每一个数,i<n-1是因为最后一次相乘是倒数第二个数和倒数第一个数相乘
{
for (int j = i + 1; j < n; j++)//j=i+1是因为arr[i]和他后面一个数开始相乘,所以j初始化为i+1
{
sum += arr[i] * arr[j];用arr[i]后面的每一个数与arr[i]相乘,并加到sum里面
}
}
printf("%lld", sum);
return 0;
}
我们来看看提交结果只得了91分,所以显然时间复杂为o(n^2),导致超时,有没有更优化的方案呢
下面来看看优化后的方案
先来看看思路
sum=a2*a1+a3*(a1+a2)+a4*(a1+a2+a3)+.............an*(a1+a2+a3+...............a(n-1))
#include<stdio.h>
int main()
{
int n = 0;
int m = 0;
scanf("%d", &n);
long long sum = 0, k = 0;
for (int i = 0; i < n; i++)
{
scanf("%d", &m);
sum += m * k;//每输入一个m就用m将前面的数乘一遍,也就相当于乘他们的和
k += m;//k用来实现每输入一个m就将它加到k里面
}
printf("%lld", sum);
return 0;
}
显然时间复杂度从o(n^2)降到了o(n),来看看测试结果