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();
}
posted @ 2022-09-14 11:46  Prean  阅读(22)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};