CF848D题解
考虑如果边 \((u,w),(w,v)\) 是从 \((u,v)\) 分裂出来的,那么 \((u,v)\) 这条边有一个儿子,儿子是一个二元组为 \(((u,w),(w,v))\)。
容易发现所有本质不同的分裂方案对应所有本质不同的树。
考虑最小割对应什么。对于一个根节点,必须将所有儿子都割完之后才能割掉自己,所以有一个类似:
\[f[n][m]=\sum_{\sum(a_i+b_i)=n,\sum(\min(x_i,y_i))+1=m}f[a_i][x_i]\times f[b_i][y_i]
\]
的东西。
实际上这样还是有可能会算重(原问题是无序的,背包是有序的)。设:
\[g[n][m]=\sum_{a+b+1=n,\min(x,y)=m}f[a][x]\times f[b][y]
\]
来进行辅助计算。
容易发现 \(g[n][m]\) 对应的任意二元组形态都不同。
先考虑用相同的 \(g[n][m]\) 填充一个集合,然后用所有的集合去填充 \(f\)。
设 \(G[n][m]\) 表示所有二元组都是 \(g[n][m]\) 集合中的元素,容易知道这个方案数是:
\[G[n][m]=\sum[x^i](\frac{1-x^{i+1}}{1-x})^{g[n][m]}=\sum\binom{i+g[n][m]-1}{i}x^{in}y^{im}
\]
说人话就是
设 \(G[n][m][k]\) 表示使用 \(k\) 个 \(g[n][m]\) 去填充集合,那么 \(G[n][m][k]=g[n][m]^{\overline{k}}\)
然后把 \(G\) 卷起来就能得到 \(f\) 了。
复杂度是 \(O(n^6\ln n)\),还不够,考虑优化。
有一件非常厉害之处在于,对于 \(f[n][m]\),不满足 \(x\leq n\and y\leq m\) 的部分对 \(f[n][m]\) 都没有贡献。
也就是说我们可以对所有的 \(g\) 做一个大背包,这样虽然加入了别的元素但是一定不会影响到答案。
复杂度降低至 \(O(n^4\ln n)\)。
当然要是在模拟赛遇到了这种鬼东西,肯定是写个 \(O(n^6\ln n)\) 打表闷声发大财啦。
#include<cstdio>
namespace SOLVE{
const int M=55,mod=1e9+7;
int n,m,inv[M],f[M][M],g[M][M],h[M][M];bool v1[M][M],v2[M][M];
inline int F(const int&n,const int&m);
inline void G(const int&n,const int&m);
inline int F(const int&n,const int&m){
if(n<m)return 0;if(!n||!m)return n==m;if(v1[n][m])return f[n][m];
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)G(i,j);return v1[n][m]=true,f[n][m]=h[n][m];
}
inline void G(const int&n,const int&m){
if(n<m||!n||!m||v2[n][m])return;v2[n][m]=true;
for(int x(0),y(n-1);x<=n-1&&y>=0;++x,--y){
int sum;
sum=0;for(int k=m-1;k<=x;++k)sum=(sum+F(x,k))%mod;g[n][m]=(g[n][m]+1ll*F(y,m-1)*sum)%mod;
sum=0;for(int k=m;k<=y;++k)sum=(sum+F(y,k))%mod;g[n][m]=(g[n][m]+1ll*F(x,m-1)*sum)%mod;
}
static int c[M];c[0]=1;
for(int k=1;k*n<=SOLVE::n&&k*m<=SOLVE::n;++k)c[k]=1ll*(g[n][m]+k-1)*inv[k]%mod*c[k-1]%mod;
for(int i=SOLVE::n;i;--i)for(int j=SOLVE::n;j;--j)for(int k=1;n*k<=i&&m*k<=j;++k){
h[i][j]=(h[i][j]+1ll*c[k]*h[i-n*k][j-m*k])%mod;
}
}
inline void main(){
scanf("%d%d",&n,&m);h[0][0]=1;
inv[1]=1;for(int i=2;i<=n;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;printf("%d",F(n,m-1));
}
}
signed main(){
SOLVE::main();
}