牛客挑战赛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;
}