Codeforces917D Stranger Trees【生成樹方案數樹形DP】

題目描述:

給出一棵nn個點的無邊權無向樹。對每個k[0,n1]k\in[0,n-1],求出恰有kk條邊與原樹重合的nn個點的樹的數量。

題目分析:

O(n4)O(n^4)的插值解法已經被吊打了。

首先求出強制kk條邊相等,剩下的邊任意的方案數g(k)=ik(ik)f(i)g(k)=\sum_{i\ge k}\binom ikf(i),二項式反演/容斥一下可得f(k)=ik(1)ik(ik)g(i)f(k)=\sum_{i\ge k}(-1)^{i-k}\binom ikg(i)。於是問題就是求g(k)g(k)

而強制kk條邊相等就是選出nkn-k個連通塊,於是問題轉化爲求把原樹劃分爲kk個連通塊後的生成樹方案數。

由prufer序列可知,如果有kk個連通塊,每個大小是aia_i,那麼生成樹的方案數是nk2ain^{k-2}\prod a_i

於是樹形DP求生成樹方案數,如果不帶ai\prod a_i就是求劃分kk個連通塊的方案數,這個可以O(n2)O(n^2)求,而帶上權值後需要一個小 trick\texttt {trick},相當於方案數變爲在每個連通塊裏面再選一個點。
f[i][j][0/1]f[i][j][0/1]表示ii子樹內劃分爲jj個連通塊,ii所在的連通塊 沒有選/已經選了 點的方案數,那麼合併兩邊的時候jj個連通塊 + kk個連通塊可以貢獻到 j+kj+k個連通塊;或者合併成一個貢獻到j+k1j+k-1個連通塊,合併的時候有情況需要選點,由乘法分配律,相當於左邊選了點*右邊沒選+左邊沒選*右邊選了的方案數。(口胡,詳見代碼)

Code:

#include<bits/stdc++.h>
#define maxn 105
using namespace std;
const int mod = 1e9+7;
int n,f[maxn][maxn][2],g[maxn][2],ans[maxn],siz[maxn],C[maxn][maxn];
int fir[maxn],nxt[maxn<<1],to[maxn<<1],tot;
void line(int x,int y){nxt[++tot]=fir[x],fir[x]=tot,to[tot]=y;}
#define add(x,y) x=(x+(y))%mod
void dfs(int u,int ff){
	siz[u]=f[u][1][0]=f[u][1][1]=1;
	for(int i=fir[u],v;i;i=nxt[i]) if((v=to[i])!=ff){
		dfs(v,u);
		memcpy(g,f[u],sizeof f[u]),memset(f[u],0,sizeof f[u]);
		for(int j=1;j<=siz[u];j++)
			for(int k=1;k<=siz[v];k++){
				add(f[u][j+k][0],1ll*g[j][0]*f[v][k][1]);
				add(f[u][j+k][1],1ll*g[j][1]*f[v][k][1]);
				add(f[u][j+k-1][0],1ll*g[j][0]*f[v][k][0]);
				add(f[u][j+k-1][1],1ll*g[j][1]*f[v][k][0]+1ll*g[j][0]*f[v][k][1]);
			}
		siz[u]+=siz[v];
	}
}
int Pow(int a,int b){int s=1;for(;b;b>>=1,a=1ll*a*a%mod) b&1&&(s=1ll*s*a%mod);return s;}
int main()
{
	scanf("%d",&n);
	for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),line(x,y),line(y,x);
	dfs(1,0);
	for(int i=1;i<=n;i++) ans[n-i]=1ll*f[1][i][1]*(i>1?Pow(n,i-2):Pow(n,mod-2))%mod;
	for(int i=0;i<n;i++) for(int j=C[i][0]=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++) add(ans[i],1ll*(j-i&1?-1:1)*C[j][i]*ans[j]);
		printf("%d%c",(ans[i]+mod)%mod,i==n-1?10:32);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章