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

本文详细解析了NOIP模拟赛中的一道数学+前缀和算法题,通过两次前缀和技巧优化求解过程,实现了高效算法设计。文章提供了完整的C++代码实现,并深入解释了每一步操作背后的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接: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)

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值