Processing math: 100%

AtCoder Beginner Contest 231 G - Balls in Boxes 简要题解

提供一个生成函数的推法。

考虑把最后的答案写出来:

c1++cn=kk!nkni=1ci!ni=1(Ai+ci)

这个式子的意思是把可能的一种增加方案(c1,,cn)枚举出来,算出达到这种方案的情况数(k!ci!),再算出概率和这种方案的贡献。

观察这个式子,和第i个元素相关的部分为Ai+cici!,把这东西写成EGF的形式就是Fi(x)=ex(Ai+x),所以答案也就变成了:

[xk]k!nkni=1ex(Ai+x)=[xk]k!nkenxni=1(Ai+x)

乘积部分是一个n次多项式,不需要分治ntt可以直接暴力算,又众所周知enx=i=0(nx)ii!,把对应项乘起来就可以了。

namespace My_Math{
    #define N 100000

    int fac[N+100],invfac[N+100];

    int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    int mul(int x,int y) {return 1ll*x*y%maxd;}
    ll qpow(ll x,int y)
    {
        ll ans=1;
        while (y)
        {
            if (y&1) ans=mul(ans,x);
            x=mul(x,x);y>>=1;
        }
        return ans;
    }
    int getinv(int x) {return qpow(x,maxd-2);}

    int C(int n,int m)
    {
        if ((n<m) || (n<0) || (m<0)) return 0;
        return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    }

    void math_init()
    {
        fac[0]=invfac[0]=1;
        rep(i,1,N) fac[i]=mul(fac[i-1],i);
        invfac[N]=getinv(fac[N]);
        per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    }
    #undef N
}
using namespace My_Math;

int n,k,f[N][N];

int main()
{
    f[0][0]=1;
    n=read();k=read();
    rep(i,1,n) 
    {
        int a=read();
        f[i][0]=mul(f[i-1][0],a);
        rep(j,1,i) f[i][j]=add(f[i-1][j-1],mul(f[i-1][j],a));
    }
    int ans=0,prod=1,inv=getinv(qpow(n,k));
    rep(i,0,min(k,n))
    {
        int tmp=mul(prod,qpow(n,k-i));        
        tmp=mul(tmp,inv);
        ans=add(ans,mul(tmp,f[n][i]));
        prod=mul(prod,k-i);
    }
    printf("%d\n",ans);
    return 0;
}
posted @   EncodeTalker  阅读(127)  评论(2编辑  收藏  举报
点击右上角即可分享
微信分享提示