LG5178 求和

求和

给定数列 \(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;
}

posted on 2020-01-13 15:04  autoint  阅读(207)  评论(0编辑  收藏  举报

导航