• CF917D Stranger Trees


    CXX.CF917D Stranger Trees

    这里是本题的DP解法。矩阵树定理解法详见矩阵树定理学习笔记中重题III.TopCoder13369-TreeDistance

    首先,一个基础结论是,如果一张 \(n\) 个点的图,被连成一棵森林,则继续加边连成一棵树的方案数是 \(n^{k-2}\prod\limits_{i=1}^kc_i\),其中森林中共有 \(k\) 棵树,第 \(i\) 棵树的大小是 \(c_i\)

    然后,考虑二项式反演。设 \(g_i\) 是至多有 \(i\) 条边在原树上的方案数。二项式反演一下即可得到恰好有 \(i\) 条边在原树上的方案数。则问题被转化为求出 \(g\) 数组。\(g\) 数组中 \(n^{k-2}\) 的部分是可以提出来统一计算的。考虑使用DP来求出 \(g\) 的另一部分。设 \(f_{i,j,k}\) 表示 \(i\) 的子树中被截成 \(j\) 棵树,且 \(i\) 节点自身所在树大小为 \(k\) 的权值(不包括 \(i\) 自身的树)和。合并节点 \(i\) 和儿子 \(i'\) 时,只需对二者处于同一连通块或是不同连通块进行树上背包分开转移即可。

    时间复杂度 \(O(n^4)\),是树上背包复杂度。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    int n,f[110][110][110],g[110],sz[110],h[110][110],fac[110],inv[110];
    vector<int>v[110];
    int ksm(int x,int y=mod-2){
    	int z=1;
    	for(;y;y>>=1,x=1ll*x*x%mod)if(y&1)z=1ll*z*x%mod;
    	return z;
    }
    void dfs(int x,int fa){
    	sz[x]=1,f[x][1][1]=1;
    	for(auto y:v[x]){
    		if(y==fa)continue;
    		dfs(y,x);
    		for(int i=1;i<=sz[x];i++)for(int I=1;I<=sz[y];I++)for(int j=1;j<=sz[x];j++)for(int J=1;J<=sz[y];J++){
    			(h[i+I][j]+=1ll*f[x][i][j]*f[y][I][J]%mod*J%mod)%=mod;
    			(h[i+I-1][j+J]+=1ll*f[x][i][j]*f[y][I][J]%mod)%=mod;
    		}
    		for(int i=1;i<=sz[x]+sz[y];i++)for(int j=1;j<=sz[x]+sz[y];j++)f[x][i][j]=h[i][j],h[i][j]=0;
    		sz[x]+=sz[y];
    	}
    }
    int C(int x,int y){return 1ll*fac[x]*inv[y]%mod*inv[x-y]%mod;}
    int main(){
    	scanf("%d",&n);
    	for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x);
    	fac[0]=1;for(int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mod;
    	inv[n]=ksm(fac[n]);for(int i=n-1;i>=0;i--)inv[i]=1ll*inv[i+1]*(i+1)%mod;
    	dfs(1,0);
    	for(int i=0,k=ksm(n);i<n;i++,k=1ll*k*n%mod){
    		for(int j=1;j<=n;j++)(g[i]+=1ll*f[1][i+1][j]*j%mod)%=mod;
    		g[i]=1ll*g[i]*k%mod;
    	}
    	for(int i=0;i<n;i++)for(int j=0;j<i;j++)(g[i]+=mod-1ll*g[j]*C(n-j-1,i-j)%mod)%=mod;
    	for(int i=0;i<n;i++)printf("%d ",g[n-i-1]);
    	return 0;
    }
    

  • 相关阅读:
    idea用法
    pagehelper用法
    mybatis
    多线程2
    radio 标签状态改变时 触发事件
    多线程
    a标签点击后,给a标签添加样式
    servlet
    mybatis 查询
    springmvc 发送PUT 和 DELETE 请求
  • 原文地址:https://www.cnblogs.com/Troverld/p/14601370.html
Copyright © 2020-2023  润新知