牛客国庆集训派对Day4——G 区间权值(找规律,双重前缀和)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hxxjxw/article/details/82939321

题目链接:https://www.nowcoder.com/acm/contest/204/G

题目大意:
      小 Bo 有 n 个正整数 a1..an,以及一个权值序列 w1…wn,现在他定义
      现在他想知道 的值,需要你来帮帮他。你只需要输出答案对 109+7 取模后的值

题解:

题目要求的是

 f(1,1)+f(1,2)+f(1,3)+...+f(1,n)

f(2,2)+f(2,3)+...+f(2,n)

f(3,3)+f(3,4)+...+f(3.n)

f(4,4)+f(4,5)...

...

f(n,n)

扫描二维码关注公众号,回复: 3441101 查看本文章

sum[1]w1\ + \ sum[2]w2\ +\ sum[3]w3+...\ +\ sum[n]wn

(sum[2]-sum[1])w1+(sum[3]-sum[1])w2+...+(sum[n]-sum[1])w_{n-1}

(sum[3]-sum[2])w1+(sum[4]-sum[2])w2+...+(sum[n]-sum[2])w_{n-1}

可以发现每一行的对应列的w因数相同,对应相加可得

w1(sum[n])

w2(sum[n]-sum[n-1]-sum[1])

w3(sum[n]-sm[n-1]-sum[n-2]-sum[2]-sum[1])

但是这样求的话也是需要两重循环来求......于是再来一次前缀和(S[n]为sum的前缀)

即  wi(S_{n}-S_{n-i}-S_{i-1})

#include <cstdio>
#include <cstring>
#include <cmath>
#include<algorithm>
#include<iostream>
#define mod 1000000007
using namespace std;
typedef long long ll;
ll sum[300010];
ll S[300010];
int a[300010],w[300010];
int main()
{
    //freopen("input.txt","r",stdin);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;++i)
        scanf("%d",&w[i]);
    for(int i=1;i<=n;++i)
        S[i]=S[i-1]+sum[i],S[i]%=mod;
    ll ans=0;
    for(int i=1;i<=n;++i)
    {
        ans+=((S[n]-S[n-i]-S[i-1]+mod)%mod*w[i]%mod)%mod;
        ans%=mod;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hxxjxw/article/details/82939321