牛客挑战赛44 D 数列的和

https://ac.nowcoder.com/acm/contest/8051/D

一个长度为\(n\)的数列满足\(\sum a_i\le m\),它的贡献为\((m-\sum a_i)(\prod (a_i+K)^2-K^2)\)

求所有的这样的数列的贡献和。

\(n,m,K\le 10^6\)


生成函数吼题。

答案为\(\sum(m-j)[x^j](\sum(i+2K)ix^i)^n\)

先用个比较优美的方式表示\(\sum(i+2K)ix^i\)
\(\sum(i+2K)ix^i=\sum i(i+1)x^i+\sum(2K-1)x^i=\frac{2x}{(1-x)^3}+\frac{2K-1}{(1-x)^2}\)

(总结一下:当要把形如\(\sum_iF(i)x^i\)的式子化成封闭的优美形式时,可以把\(F(x)\)变成上升幂多项式)

继续推:

\((\frac{2x}{(1-x)^3}+\frac{2K-1}{(1-x)^2})^n=\frac{2^nx^n}{(1-x)^{2n}}(\frac{1}{1-x}+c)^n=2^n\sum_{i=0}^n\frac{x^n}{(1-x)^{2n+i}}\binom{n}{i}c^{n-i}\)

\(c\)为常数。

\(\sum_{j=n}^m(m-j)[x^j]2^n\sum_{i=0}^n\frac{x^n}{(1-x)^{2n+i}}\binom{n}{i}c^{n-i}=2^n\sum_{j=n}^m(m-j)\sum_{i=0}^n\binom{i+j+n-1}{i+2n-1}\binom{n}{i}c^{n-i}=2^n\sum_{i=0}^n\binom{n}{i}c^{n-i}\sum_{j=n}^m(m-j)\binom{i+j+n-1}{i+2n-1}\)

\(\sum_{j=n}^m(m-j)\binom{i+j+n-1}{i+2n-1}=\sum_{j=n}^m\sum_{k=j+1}^m\binom{i+j+n-1}{i+2n-1}=\sum_{k=n}^m\sum_{j=n}^{k-1}\binom{i+j+n-1}{i+2n-1}=\binom{i+n+m}{i+2n+1}\)

所以答案为\(2^n\sum_{i=0}^n\binom{n}{i}c^{n-i}\binom{i+n+m}{i+2n+1}\)

可以\(O(n)\)解决。


using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 2000010
#define ll long long
#define mo 998244353
ll qpow(ll x,ll y=mo-2){
	ll r=1;
	for (;y;y>>=1,x=x*x%mo)
		if (y&1)
			r=r*x%mo;
	return r;
}
ll fac[N],ifac[N];
void initC(int n){
	fac[0]=1;
	for (int i=1;i<=n;++i)
		fac[i]=fac[i-1]*i%mo;
	ifac[n]=qpow(fac[n]);
	for (int i=n-1;i>=0;--i)
		ifac[i]=ifac[i+1]*(i+1)%mo;
}
ll C(int m,int n){
	if (m<n) return 0;
	return fac[m]*ifac[n]%mo*ifac[m-n]%mo;
}
int n,m,k;
int main(){
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	scanf("%d%d%d",&n,&m,&k);
	initC(m*2+n*2);
	ll c=(2*k-1+mo)*qpow(2)%mo,invc=qpow(c);
	ll ans=0;
//	for (int j=n;j<=m;++j){
//		ll s=0;
//		for (int i=0;i<=n;++i)
//			(s+=C(n,i)*qpow(c,n-i)%mo*C(i+j+n-1,j-n))%=mo;
//		(ans+=s*(m-j))%=mo;
//	}
//	ans=ans*qpow(2,n)%mo;
	for (int i=0;i<=n;++i){
		ll s=C(i+n+m,i+2*n+1);
//		for (int k=n;k<=m;++k)
//			s+=C(i+n+k-1,i+2*n);
//		s%=mo;
		(ans+=C(n,i)*qpow(c,n-i)%mo*s)%=mo;
	}
	ans%=mo;
	ans=ans*qpow(2,n)%mo;
	printf("%lld\n",ans);
	return 0;
}
posted @ 2020-10-17 14:40  jz_597  阅读(155)  评论(0编辑  收藏  举报