计蒜客 二次求前缀和

本文深入探讨了如何使用二次前缀和算法解决区间求和问题,通过将原问题转化为求前缀和问题,有效提高了计算效率。文章详细介绍了算法的具体实现过程,包括两次求前缀和的步骤和关键代码,特别强调了在进行相减操作时应先加Mod再余Mod的重要性。

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

传送门
思路:二次求前缀和
区间问题转化为求前缀和问题。

相减一定要先加Mod再余Mod
第一次;sum[i]-sum[i-1]=t[i];

         sum[j]-sum[l-1];
         sum[j+1]-sum[l-1];
         ...
         sum[r]-sum[l-1];
         相加在一起可归结为
         sum[j]+sum[j+1]+sum[j+2]+...sum[r]-(l-r+1)*sum[l-1]
        对 sum[j]+sum[j+1]+sum[j+2]+...sum[r] 再求一次前缀和
        sum2[i]-sum2[i-1]=sum[i]; 
/*#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<cctype>
#include<stack>
#include<map>
#include<string>
#include<cstdlib>
#define ll long long
#define N 100010
#define rep(i,n) for(int i=0;i<(n);i++)
const int maxn = 10;
int a[maxn][maxn], b[maxn][maxn];
*/
#include<bits/stdc++.h>
const int mod=1000000007;
long long t[100005], sum[100005], sum2[100005];
using namespace std;
int main() {
    //ll n, m, p, q;
    ios::sync_with_stdio(false);
    long long n, m, i, j;
    cin >> n;
    for(i = 1; i <= n; i++)
        cin >> t[i];
    long long ans = 0;
    long long u, v;
    for(i = 1; i <= n; i++)
        sum[i] = (sum[i - 1] + t[i])%mod; //t[i]=sum[i]-sum[i-1]//第一次前缀和
    //for(i = 1; i <= n; i++)
    //sum2
    for(i = 1;i <= n;i++)
        sum2[i]=(sum2[i-1]+sum[i])%mod;//再求一次sum的前缀和
        long long q,l,r;
    cin >> q;
    for(i = 0; i < q; i++) {
        cin >> l >> r;
        ans=(ans+((sum2[r]-sum2[l-1]+mod)%mod-(r-l+1)*sum[l-1]%mod+mod)%mod)%mod;//***相减一定要先加Mod再余Mod***
        //for(j = l; j <= r; j++) {
            //ans = (ans+(sum[j]-sum[l-1]+mod)%mod)%mod;
        }
        cout<<ans<<endl;
    //cout << cnt << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值