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;
}
posted @ 2025-08-20 18:13  yaohaha  阅读(20)  评论(0)    收藏  举报
返回顶端