码迷,mamicode.com
首页 > 其他好文 > 详细

LG5178 求和

时间:2020-01-13 16:21:51      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:while   利用   lock   前缀   题解   n+2   int   turn   printf   

求和

给定数列 \(a_1...a_n\)\(x_0\)

满足

\[ f_{i.j}=\begin{cases} a_i & j=0,i\leq n\x_0 & j=0,i=n+1\f_{i,j-1}+f_{i-1,j-1} & 0 < i,j \leq n+1,j < i\0 & i\leq j \end{cases} \]

\[ \sum_{i=0}^{n+1}\sum_{j=0}^{n+1}f_{i,j} \]

但这样太水了

于是给出 \(m\) 个操作,每次将 \(a_l\dots a_r~(0\le l,r \le n)\)\(p\),对于每个操作,输出答案。

特别地,若 \(0\)\(l\dots r\) 范围内,我们认为 \(x_0\) 也加 \(p\)

另外,在读入 \(m\) 个操作前,你也应该输出答案。

由于答案可能过大,输出答案对 \(1234567891\) 取模的结果。

\(n,m \leq 10^5\)

题解

https://www.luogu.com.cn/blog/user7035/solution-p5178

大概可以画出这样的图:

行\列0123...n-1n
1a1000...00
2a2f2,100...00
3a3f3,1f3,20...00
........................
nanfn,1fn,2fn,3...fn,n-10
n+1anfn+1,1fn+1,2fn+1,3...fn+1,n-1fn+1,n

每个点都对右方和右下方的元素有贡献。那么

\[ f_{i,j}=\begin{cases} 0 & i\leq j\\sum_{k=0}^j\binom{j}{k}a_{i-k} & i>j \end{cases} \]

开始大力推式子。

\[ ans=\sum_{i=1}^{n+1}\sum_{j=0}^{i-1}f_{i,j}=\sum_{i=1}^{n+1}\sum_{j=0}^{i-1}\sum_{k=0}^j\binom{j}{k}a_{i-k} \]

在这道题里面我们显然是要对组合数进行操作来减少求和符号的数量。

反复利用

\[ \sum_{i=m}^n\binom{i}{m}=\binom{n+1}{m+1} \]

\[ ans=\sum_{i=1}^{n+1}\sum_{k=0}^{i-1}a_{i-k}\sum_{j=k}^{i-1}\binom{j}{k}\=\sum_{i=1}^{n+1}\sum_{k=1}^ia_k\sum_{j=i-k}^{i-1}\binom{j}{k}\=\sum_{i=1}^{n+1}\sum_{k=1}^ia_k\sum_{j=1}^k\binom{i-j}{i-k}\=\sum_{k=1}^{n+1}a_k\sum_{i=k}^{n+1}\sum_{j=1}^k\binom{i-j}{i-k}\=\sum_{k=1}^{n+1}a_k\sum_{j=1}^k\sum_{i=0}^{n+1-k}\binom{i+k-j}{i}=\sum_{k=1}^{n+1}a_k\sum_{j=1}^k\sum_{i=0}^{n+1-k}\binom{i+k-j}{k-j}\=\sum_{k=1}^{n+1}a_k\sum_{j=1}^k\binom{n-j+2}{k-j+1}=\sum_{k=1}^{n+1}a_k\sum_{j=1}^k\binom{n-j+2}{n-k+1}\=\sum_{k=1}^{n+1}a_k\sum_{j=n-k+2}^{n+1}\binom{j}{n-k+1}\=\sum_{k=1}^{n+1}a_k\left(\binom{n+2}{n-k+2}-1\right) \]

维护系数的前缀和即可。时间复杂度 \(O(n+m)\)

CO int N=6e5+10;
int fac[N],ifac[N];
int a[N],pool[N],*s=pool+1;

IN int binom(int n,int m){
    return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
int main(){
    int n=read<int>(),m=read<int>();
    fac[0]=1;
    for(int i=1;i<=n+2;++i) fac[i]=mul(fac[i-1],i);
    ifac[n+2]=fpow(fac[n+2],mod-2);
    for(int i=n+1;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
    for(int i=1;i<=n+1;++i)if(read(a[i])<0) a[i]+=mod;
    int ans=0;
    s[0]=binom(n+2,1)-1;
    ans=mul(a[n+1],s[0]);
    for(int i=1;i<=n;++i){
        s[i]=add(s[i-1],binom(n+2,n-i+2)-1);
        ans=add(ans,mul(a[i],binom(n+2,n-i+2)-1));
    }
    printf("%d\n",ans);
    while(m--){
        int l=read<int>(),r=read<int>(),p=read<int>();
        if(p<0) p+=mod;
        ans=add(ans,mul(add(s[r],mod-s[l-1]),p));
        printf("%d\n",ans);
    }
    return 0;
}

LG5178 求和

标签:while   利用   lock   前缀   题解   n+2   int   turn   printf   

原文地址:https://www.cnblogs.com/autoint/p/12187362.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!