标签:变换 数加 fft 枚举 不能 没有 存在 并且 cpp
参考:当小球遇上盒子
默认问题:把 n 个小球放到 m 个盒子里,分别有三项要求:
①球是否相同 ②盒子是否相同 ③能否有空盒。
利用插板法,n 个小球中间会存在 n-1 个空,用 m-1 块板插入这些空中,可以将 n 个小球分为 m 块,因此:
\[ ans=C_{n?1}^{m?1} \]
我们现在假设有 m+n 个球然后我们用 m-1 块板将它分隔成了 m 块,然后,我们在每一块中都拿出一个小球,那么现在我们剩下 n 个小球,并且也保证了可以有空盒出现的情况,因此:
\[ ans=C_{n+m?1}^{m?1} \]
每一个球都有 m 种选择,那么总共有 n 个球,因此:
\[ ans=m^n \]
\[ ans=S2(n,m)={\frac 1 {m!}}*\sum_{k=0}^{m}(-1)^k{C_m^k}*(m-k)^n \]
\(m^n\) 的意思表示的是将\(n\)个球,\(m\)个盒子按照3来放,其中就包括了可能只放了\(m\)个或者\(m-1\)或者\(m-2\)等等的情况,那\((m-1)^n\)中又包括了只放了\(1<=i<=m-1\)的情况,如果说想表示\(m\)个相同盒子,\(n\)个不同球的放置,不能够单纯的靠\(m^n-(m-1)^n\)来实现,因为\(m^n\)包含了两个\((m-1)^n\)而这两个\((m-1)^n\)中所包含的\((m-2)^n\)又会有交集(即可能出现重复),因此需要用到容斥。最后乘\(1/m!\)是为了消除其有序性。
可以用 FFT(快速傅里叶变换)加速
与4唯一的不同就是盒子出现的有序性,因此只需要在上一个公式里不除\(m!\)即可
\[ ans=m!*S2(n,m)=\sum_{k=0}^{m}(-1)^k{C_m^k}*(m-k)^n \]
因为可以有空盒,我们可以枚举每次一共用了几个盒子,然后把相应的第二类斯特林数加起来就可以了,因此:
\[ ans=\sum_{i=1}^mS2(n,i) \]
这种数叫做贝尔数,可以说贝尔数就是其对应的第二类斯特林数之和,贝尔数对应公式:
\[ B_{n+1}=\sum_{k=0}^nC_n^kB_k \]
即枚举包含最后一个元素的集合大小,也可以通过对应的第二类斯特林数求和得到,公式如下:
\[ B_n=\sum_{k=1}^nS2(n,k) \]
设 \(f[n][m]\) 为 \(n\) 个球放到 \(m\) 个盒子里的方案数
如果只有一个盘子或者没有小球,方案数自然为 1
如果小球比盒子要少,小球肯定是放不满盒子的,由于盒子相同,可以得到转移 \(f[i][j]=f[i][i]\)
如果小球比盒子要多,就分为将盘子放满和没放满两种情况,即 \(f[i][j]=f[i?j][j]+f[i][j?1]\)
代码:
for(int i=0;i<=n;i++){ for(int j=1;j<=m;j++){ if(j==1 || i==0) f[i][j]=1; else if(i<j) f[i][j]=f[i][i]; else if(i>=j) f[i][j]=f[i-j][j]+f[i][j-1]; } }
有点类似于第一、二种情况之间的关系。
我们先假设在每一个盒子里都放上了一个球,就跟上面的情况一样了。
\[ ans=f[n?m][m] \]
标签:变换 数加 fft 枚举 不能 没有 存在 并且 cpp
原文地址:https://www.cnblogs.com/CADCADCAD/p/11372377.html