1104. Sum of Number Segments (20)-PAT甲级真题(连续序列)
Given a sequence of positive numbers, a segment is defined to be a consecutive subsequence. For example, given the sequence {0.1, 0.2, 0.3, 0.4}, we have 10 segments: (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4).
Now given a sequence, you are supposed to find the sum of all the numbers in all the segments. For the previous example, the sum of all the 10 segments is 0.1 + 0.3 + 0.6 + 1.0 + 0.2 + 0.5 + 0.9 + 0.3 + 0.7 + 0.4 = 5.0.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N, the size of the sequence which is no more than 105. The next line contains N positive numbers in the sequence, each no more than 1.0, separated by a space.
Output Specification:
For each test case, print in one line the sum of all the numbers in all the segments, accurate up to 2 decimal places.
Sample Input:
4
0.1 0.2 0.3 0.4
Sample Output:
5.00
题目大意:求各个连续序列的和
思路:开始是想要暴力求解的,发现运行超时了,因为n <= 1e5,如果暴力求解的话,时间复杂度达到O(n^2),只能使用小于等于时间复杂度为O(nlog(n))的算法求解,需要优化一下。
那应该怎么优化呢?关键是要找到每个元素在所有子段中出现的次数,然后用每个元素乘以它出现的次数,再求和,这样时间复杂度就是 O (N),就可以处理大 N 了。
那接下来的问题是,每个元素 a [i](假设下标从 0 开始)在多少个子段中出现呢?需要确定这个次数。
因为子段必须连续,所以起点不能晚于 i,终点不能早于 i。i从1开始。
一个元素a[i]要出现在一个连续序列中,那这个序列的左端点必须:l <= i,右端点一共有i种可能,那它的右端点必须:r >= i,一共有(n-i+1)种可能,一共是i*(n-i+1)种,然后乘以a[i],再累加起来即可。
#include <iostream>
using namespace std;
//懂了是懂了,但我怎么保证我下次会写这种题?
int main() {
int n;
cin >> n;
long long sum = 0;
double temp;
for (int i = 1; i <= n; i++) {
cin >> temp;
sum += (long long)(temp * 1000) * i * (n - i + 1);
}
printf("%.2f", sum / 1000.0);
return 0;
}

浙公网安备 33010602011771号