• Easy【生成函数】


    题意

    若序列 (A,B) 满足 (sum_{i=1}^{K}{a_i}=N,sum_{i=1}^{K}{b_i}=M) ,则其对答案的贡献是:(P=prod_{i=1}^{K}{min(a_i,b_i)}),问所有满足条件的序列的总贡献为多少。

    (1leq N,M leq 10^6,1leq K leq min(N,M))

    https://ac.nowcoder.com/acm/contest/5670/C

    分析

    如果本题求的是构造的序列 (A,B) 的方案总数,那么可以构造下列的生成函数:

    [S=(x+x^2+x^3+dots +x^N)^K*(y+y^2+y^3+dots +y^M)^K ]

    答案为展开式中 (x^Ny^M) 的系数。

    但题目要求:

    [prod_{i=1}^{K}{min(a_i,b_i)} ]

    因此,可以构造生成函数:?

    [S=sum_{i,jin [1,infty)}{min(i,j)x^iy^j} ]

    那么,最终的答案为 (S^K) 的展开式中 (x^Ny^M) 的系数。

    [egin{align} S &= xy+xy^2+xy^3+dots \ &+x^2y+2x^2y^2+2x^2y^3+dots\ &+x^3y+2x^3y^2+3x^3y^3+dots\ end{align} ]

    两边同时乘上 (x),有:

    [egin{align} xS &= 0+0+0+dots\ &+ x^2y+x^2y^2+x^2y^3+dots\ &+ x^3y+2x^3y^2+2x^3y^3+dots\ end{align} ]

    两式相减,得:

    [egin{align} S-xS &= xy+xy^2+xy^3+dots\ &+0+x^2y^2+x^2y^3+dots\ &+0+0+x^3y^3+dots end{align} ]

    (f(1)=xy(1+y+y^2+y^3+dots) , f(n)=xyf(n-1)),则:

    [S-xS=sum_{i=1}^{infty}{f(i)}=f(1)*(1+xy+x^2y^2+dots)=xy*(1+y+y^2+dots)*(1+xy+x^2y^2+dots) ]

    (G(x)=1+x+x^2+x^3+dots),那么 (S(1-x)=xy*G(y)*G(xy))

    因为 (G(x)=xG(x)+1),即 (G(x)=frac{1}{1-x}),因此:(S=xy*G(x)*G(y)*G(xy)),所以有:

    [S^K=x^Ky^KG(x)^KG(y)^KG(xy)^K ]

    又根据广义二项式定理

    [frac{1}{(1-x)^n}=sum_{i=0}^{infty}{C_{n+i-1}^{i-1}x^i} ]

    [G(x)^K=sum_{i=0}^{infty}{C_{K+i-1}^{i-1}{x^i}} ]

    在生成函数中,(x^Ny^M) 的系数为答案,而多项式前面已经有了 (x^Ky^K)。因此,可以在 ([0,min(N,M)-K]) 内枚举 (xy) 的系数,然后根据 (N)(M) 补全出 (x)(y) 的系数,最终得到答案:

    [ans=sum_{i=0}^{min(N,M)-K}{C_{K+(N-K-i)-1}^{K-1}*C_{K+(M-K-i)-1}^{K-1}*C_{K+i-1}^{K-1}} ]

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    const int N=1e6+6;
    ll fac[N],inv[N];
    ll power(ll a,ll b)
    {
        ll res=1;
        a%=mod;
        while(b)
        {
            if(b&1) res=res*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return res;
    }
    void init()
    {
        int maxn=1e6;
        fac[0]=1;
        for(int i=1;i<=maxn;i++)
            fac[i]=fac[i-1]*i%mod;
        inv[maxn]=power(fac[maxn],mod-2);
        for(int i=maxn-1;i>=0;i--)
            inv[i]=1LL*inv[i+1]*(i+1)%mod;
    }
    int main()
    {
        int T,n,m,k;
        init();
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            ll ans=0;
            int minn=min(n,m);
            for(int i=0;i<=minn-k;i++)//枚举
            {
                ll t1=fac[k+i-1]*inv[k-1]%mod*inv[i]%mod;
                ll t2=fac[n-i-1]*inv[k-1]%mod*inv[n-k-i]%mod;
                ll t3=fac[m-i-1]*inv[k-1]%mod*inv[m-k-i]%mod;
                ans=(ans+t1*t2%mod*t3)%mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    

    参考博客:https://zhuanlan.zhihu.com/p/234938833

  • 相关阅读:
    比较@Resource、@Autowired
    Spring boot注解(annotation)含义详解
    Ubuntu进不去,显示error:unknown filesystem (最简单解决方案总结)
    自动更新变成灰色的解决方法
    桌面图标有阴影怎么去掉
    彻底禁止QQ更新
    重命名nginx服务器
    discuz 学习
    Ubuntu 更新源
    鼠标使用技巧 让网页自动向下翻或向上翻
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13668696.html
Copyright © 2020-2023  润新知