十二重计数法 题解

\(146\) 行,有 \(80\) 行都是多项式板子(主要 \(\exp\) 真的长)。可以说涵盖了相当一部分球盒模型了,当然算是比较基础的小练习。

好了开始。

题意

\(n\) 个球放到 \(m\) 个盒子里,在以下的十二种限制条件(球相同/不同,盒子相同/不同,每个盒子无限制/至多一个球/至少一个球)下求方案数。

题解

\(\text{I}\) :球互不相同,盒子互不相同。

每个球都有 \(m\) 种不同的放法, \(n\) 个球,总数就是 \(m^n\)

\(\text{II}\) :球互不相同,盒子互不相同,每个盒子至多一个球。

相当于从 \(m\) 个盒子里选出 \(n\) 个来放球,显然是 \(A_m^n\)

\(\text{III}\) :球互不相同,盒子互不相同,每个盒子至少一个球。

注意我们不能先每个盒子钦定放进去一个球然后剩下的随便放。因为这样会算重复。

举个例子:考虑 \(n=5,m=4\) 的情况:一开始我们随便放四个球(比如 \(1,2,3,4\) ),然后放第 \(5\) 个(假如和 \(1\) 放一块),那么这个方案就是 \(\{1,5\},\{2\},\{3\},\{4\}\) 。然后再选四个( \(2,3,4,5\) ),然后放第 \(1\) 个,如果按照上面的算,那么就可以和第 \(5\) 个放一块,就算重复了。

我们发现这个就是把 \(1-n\)\(n\) 个元素分成 \(m\) 个有序集合,而分成 \(m\) 个无序集合的方案数显然是 \(\begin{Bmatrix}n \\ m\end{Bmatrix}\) 。然后我们要变得有序,直接乘一个 \(m!\) 就行了。答案就是 \(m!\begin{Bmatrix}n \\ m\end{Bmatrix}\)

\(\text{IV}\) :球互不相同,盒子全部相同。

一开始想到了贝尔数,但是贝尔数是任意个集合。类推 \(Bell(n)=\sum_{i=0}^n\begin{Bmatrix}n \\ i\end{Bmatrix}\) ,我们可以想到枚举分了多少个盒子,于是答案就是

\[\sum_{i=0}^m\begin{Bmatrix}n\\i\end{Bmatrix} \]

\(\text{V}\) :球互不相同,盒子全部相同,每个盒子至多一个球。

降智题。发现球比盒子多的时候没法放下,而球比盒子少的时候因为盒子相同所以怎么放都一样。所以答案就是 \([n\le m]\)

\(\text{VI}\) :球互不相同,盒子全部相同,每个盒子至少一个球。

这个比较水。规定每个盒子都有球,相当于把 \(1-n\)\(n\) 个元素分成 \(m\) 个无序集合,显然是 \(\begin{Bmatrix}n\\m\end{Bmatrix}\)

\(\text{VII}\) :球全部相同,盒子互不相同。

别考虑什么别的东西(我考虑各种高深东西干不出来最后发现就是个插板)。既然球全部相同那么考虑如何把空的盒子去掉。我们添上 \(m\) 个球,然后把它们分成 \(m\) 组,于是就是 \(n+m-1\) 个空位中插入 \(m-1\) 个板,答案就是 \(\binom{n+m-1}{m-1}\)

\(\text{VIII}\) :球全部相同,盒子互不相同,每个盒子至多一个球。

现在球相同盒子不同,于是就变成了从 \(m\) 个盒子里选出 \(n\) 个放球,是 \(\binom{m}{n}\)

\(\text{IX}\) :球全部相同,盒子互不相同,每个盒子至少一个球。

既然每个盒子都有球了那就不需要新增球规定不为空了。直接插板,是 \(\binom{n-1}{m-1}\)

\(\text{XI}\) :球全部相同,盒子全部相同,每个盒子至多一个球。

同样是弱智题,也是 \([n\le m]\)

接下来是最难的两个(所以把 \(\text{XI}\) 放到前面了)。

\(\text{X}\) :球全部相同,盒子全部相同。

首先问题等价于求把 \(n\) 分拆成不超过 \(m\) 个无序整数的分拆数。由 \(\text{Ferrers}\) 图的结论可以知道,这个数就是只用 \(\le m\) 的数来分拆的方案数。

考虑分拆数的\(\text{OGF}\) (由于只用 \(\le m\) 的数分拆所以加上了上界):

\[\prod_{k=1}^m\sum_{i=0}^nx^{ik}=\prod_{k=1}^m\frac 1{1-x^k} \]

按照套路取个 \(\ln\) 然后 \(\exp\) 回来:

\[\begin{aligned} &\exp\sum_{i=1}^m\ln(\frac 1{1-x^i})\\ =&\exp\sum_{i=1}^m\sum_{j=1}^{\lfloor \frac ni \rfloor}\frac{x^{ij}}{j} \end{aligned} \]

直接暴力计算即可,答案即为第 \(n\) 项的值。

\(\text{XII}\) :球全部相同,盒子全部相同,每个盒子至少一个球。

由于球相同所以可以钦定每个盒子放一个球然后求解,答案就是上面那个多项式第 \(n-m\) 项的值。

代码一半是板子。板子没什么意思就不放了。

int A(int n,int m){
    if(n<m)return 0;
    return 1ll*jc[n]*inv[n-m]%mod;
}
int C(int n,int m){
    if(n<m)return 0;
    return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
int getstiring(int n,int m){
    int ans=0;
    for(int i=1;i<=m;i++){
        ans=(ans+1ll*((m-i)&1?(mod-1):1)*C(m,i)%mod*qpow(i,n)%mod)%mod;
    }
    return 1ll*inv[m]*ans%mod;
}
void getstiring2(int n,int b[]){
    for(int i=0;i<=n;i++){
        a[i]=(i&1)?mod-inv[i]:inv[i];
        b[i]=1ll*qpow(i,n)*inv[i]%mod;
    }
    n++;get(n<<1);
    ntt(a,wl,1);ntt(b,wl,1);
    for(int i=0;i<wl;i++)b[i]=1ll*a[i]*b[i]%mod;
    ntt(b,wl,-1);
    for(int i=n;i<wl;i++)b[i]=0;
}
void solve(){
    printf("%d\n",qpow(m,n));//I
    printf("%d\n",A(m,n));//II
    printf("%lld\n",1ll*jc[m]*getstiring(n,m)%mod);//III
    getstiring2(n,stiring);
    int ans=0;
    for(int i=0;i<=m;i++)ans=(ans+stiring[i])%mod;
    printf("%d\n",ans);//IV
    printf("%d\n",(n<=m));//V
    printf("%d\n",getstiring(n,m));//VI
    printf("%d\n",C(n+m-1,m-1));//VII
    printf("%d\n",C(m,n));//VIII
    printf("%d\n",C(n-1,m-1));//IX
    for(int i=0;i<=n;i++)a[i]=0;
    for(int i=1;i<=m;i++){
        for(int j=i;j<=n;j+=i){
            a[j]=(a[j]+qpow(j/i,mod-2))%mod;
        }
    }
    getexp(n+1,a,b);
    printf("%d\n",b[n]);//X
    printf("%d\n",(n<=m));//XI
    printf("%d\n",n>=m?b[n-m]:0);//XII
}
int main(){
    scanf("%d%d",&n,&m);jc[0]=inv[0]=1;
    for(int i=1;i<=n+m;i++)jc[i]=1ll*jc[i-1]*i%mod;
    inv[n+m]=qpow(jc[n+m],mod-2);
    for(int i=n+m-1;i>0;i--)inv[i]=1ll*inv[i+1]*(i+1)%mod;
    solve();
    return 0;
}
posted @ 2022-10-10 17:22  gtm1514  阅读(59)  评论(0编辑  收藏  举报