HDU 5086 Revenge of Segment Tree

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5086

题目大意:

 

  给定一个序列,求这个序列的子序列的和,再求所有子序列总和,这些子序列是连续的。去题目给的第二组数据的

 

3

 

1 2 3

 

这个序列的子序列有 [1]、[2]、[3]、[1、2]、[2、3]、[1、2、3],这些子序列的和是分别是1、2、3、3、5、6。再将这些和加起来

 

1+2+3+3+5+6=20这个就是最终的答案。

 

解题思路:

  我们假设n等于5。序列为1、2、3、4、5。然后我们将它们如下排列,每行表示一个序列

 

 

1

 

2

1 2

 

3

2 3

1 2 3

 

4

3 4

2 3 4

1 2 3 4

 

5

4 5

3 4 5

2 3 4 5

1 2 3 4 5

 

 

我们从中会发现序列中的a[i](表示序列第i个数),不管在那堆里面,a[i]有i个。总共有几个a[i]*i呢,可以看出有n-i+1个。

所以推出公式为∑a[i]*i*(n-i+1)就是正确的答案了

 

为什么我们要推公式,是因为我们暴力做的话时间复杂度是O(n^2),根据题目给的数据,肯定会超时。

 

推出的公式的时间复杂度是O(n),题目给的数据,是不会超时的。

代码:

#include <iostream>
#include<cstdio>
#define mod 1000000007
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int N;
        int sum=0;
        __int64 s;
        cin>>N;
        for(int i=1;i<=N;i++)
        {
            
            scanf("%I64d",&s);//此处输入得用scanf,用cin会超时
            sum=(sum+s*i%mod*(N-i+1))%mod;
        }
        printf("%d\n",sum);
      
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值