CCPC2021 广州A/CF Gym103415A

Description

给定 \(n,w\) 和长度为 \(n\) 的序列 \(c\),求

\[\sum_{\sum b_i\le w}\prod_{i=1}^nb_i^{c_i} \]

的值模 \(998244353\) 的结果

\(n\le 10^5,w\le 10^18,\sum c\le 10^5\)

Solution

写出 \(\rm OGF\) 大概可以把答案写成下式并进行一定程度的和式变换

\[\begin{aligned}Ans&=\sum_{k=0}^w[x^k]\prod_{i=1}^n\sum_{j=0}^{+\infty}j^{c_i}x^j\\ &=\sum_{k=0}^w[x^k]\prod_{i=1}^n\sum_{j=0}^{+\infty}\sum_{p=0}^{c_i}\begin{Bmatrix}c_i\\ p\end{Bmatrix}j^{\underline p}x^j\\ &=\sum_{k=0}^w[x^k]\prod_{i=1}^n\sum_{p=0}^{c_i}\begin{Bmatrix}c_i\\ p\end{Bmatrix}p!\sum_{j=0}^{+\infty}\binom jp x^j\\ &=\sum_{k=0}^w[x^k]\prod_{i=1}^n\sum_{p=0}^{c_i}\begin{Bmatrix}c_i\\ p\end{Bmatrix}p!x^p\sum_{j=0}^{+\infty}\binom {j+p}p x^j\\ &=\sum_{k=0}^w[x^k]\prod_{i=1}^n\sum_{p=0}^{c_i}\begin{Bmatrix}c_i\\ p\end{Bmatrix}p!x^p\left(\frac{1}{1-x}\right)^{p+1} \end{aligned}\]

最后一步使用了数列 \(a_n=\binom{n+m}{m}\)\(m\) 为常数)的 \(\rm OGF\)\((\frac1{1-x})^{m+1}\),证明考虑对常数 \(m\) 归纳,使用了最基础的组合数求一行的和

\(\frac 1{1-x}\) 看做自变量,剩下的看成多项式可以分治乘法求出多项式本身,但是别扭的是这个 \(x^p\),不过对于每个 \(p+1\) 都会配凑一个 \(p\)\(n\) 个式子累乘起来那么对于 \((\frac 1{1-x})^m\) 的项必然跟着一个 \(x^{m-n}\),找指数时对着等号最前面的 \([x^k]\)\(k\) 减就行了

分治乘法的叶子处需要快速求第二类斯特林数一行,由于 \(\sum c_i\) 的上界是可以接受的,那么逐个快速求就行了

剩下的工作是统计答案,考虑 \(f_px^{p-n}(\frac 1{1-x})^p\) 对某个 \(x^{r}\) 的贡献系数:现将 \(r\) 减掉 \(p-n\)\([x^{r-(p-n)}]\left(\frac{1}{1-x}\right)^p=\binom{r+n-1}{p-1}\)

直接对着 \(r\in[0,w-(p-n)]\) 求一列和就能得到 \(\binom {w+n}p\),即 \(f_p\) 对答案的贡献

组合数推一下就行了,不要直接算

写题解的初衷是看网上没有题解,所以希望能给有需要的人一些帮助吧

Code

inline poly Mul(poly a,poly b){
    int n=a.size(),m=b.size(),lim=1;
    while(lim<=(n+m)) lim<<=1;
    NTT(a,lim,1); NTT(b,lim,1);
    rep(i,0,lim-1) ckmul(a[i],b[i]);
    NTT(a,lim,-1);
    a.resize(n+m-1);
    return a;
}
inline poly Get_Line(int x){
    vector<int> a,b; a.resize(x+1); b.resize(x+1);
    for(int i=0;i<=x;++i){
        if(i&1) a[i]=mod-ifac[i]; else a[i]=ifac[i];
        b[i]=mul(ifac[i],ksm(i,x));
    }
    poly vec=Mul(a,b); vec.resize(x+1);
    return vec;
}
inline poly solve(int l,int r){
    if(l==r){
        poly str=Get_Line(c[l]);
        poly ret; ret.resize(c[l]+2);
        rep(i,0,c[l]) ret[i+1]=mul(str[i],fac[i]);
        return ret;
    }
    int mid=(l+r)>>1;
    return Mul(solve(l,mid),solve(mid+1,r));
}
signed main(){
    n=5e5; fac[0]=inv[0]=1; 
    for(int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
    ifac[n]=ksm(fac[n],mod-2);
    Down(i,n,1) ifac[i-1]=mul(ifac[i],i),inv[i]=mul(ifac[i],fac[i-1]);
    n=read(); w=read(); 
    int sumc=0;
    rep(i,1,n) sumc+=(c[i]=read());
    vector<int> f=solve(1,n);
    int ans=0,dfac=1;
    for(int i=0;i<=n+sumc;++i){
        if(i-n>w) break;
        if(i>=n){
            ckadd(ans,mul(f[i],mul(dfac,ifac[i])));
        }
        ckmul(dfac,(w+n-i)%mod);
    }
    print(ans);
    return 0;
}
原文地址:https://www.cnblogs.com/yspm/p/15765945.html