• AtCoder abc160 F


    传送门

    题意

    给一颗树,指定一个点,从这个点开始染色,每次只能在已染色点旁边染色,问从每个点开始染色分别能产生多少种染色序列。

    题解

    这个问题其实就是问一颗有根树的拓扑序列个数。
    其实我们知道不是树的有向无环图的拓扑序列个数是个np问题,但是树的拓扑序列个数是一个可解的问题。(n) 的全排列个数为 (n!),来考虑有多少种非法情况,可以发现,对于每个子树,它的根一定要在这颗子树的排列的第一个,那么这个子树的排列中只有 (frac{1}{size}) 个是合法的,那么所有排列中就只有 (frac{n!}{prod_{u=1}^{n}size[u]}) 种合法,那么一颗有根树的拓扑序列数量就是 (frac{n!}{prod_{u=1}^{n}size[u]})
    而这个题中给的是无根树,然后问每个点作为根时该树的拓扑序列个数,很明显就是一个换根dp。做法就是以 (1) 为根预处理每颗子树的大小和子树前缀积,然后换根的转移就很好写了。

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <queue>
    #define xx first
    #define yy second
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> PII;
    const int N=3e5+10;
    const int M=1e6+10;
    const int inf=0x3f3f3f3f;
    const LL INF=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    int n,siz[N];
    vector<int> g[N];
    LL fac[N],ans[N],mul[N];
    
    LL qpow(LL x,LL k){
    	LL res=1;
    	while(k){
    		if(k&1) res=res*x%mod;
    		k>>=1;
    		x=x*x%mod;
    	}
    	return res;
    }
    
    void predfs(int u,int fa){
    	siz[u]=mul[u]=1;
    	for(int v:g[u]){
    		if(v==fa) continue;
    		predfs(v,u);
    		siz[u]+=siz[v];
    		mul[u]=mul[u]*mul[v]%mod;
    	}
    	mul[u]=mul[u]*siz[u]%mod;
    }
    
    void dfs(int u,int fa,LL premul){
    	LL down=premul;
    	for(int v:g[u]) if(v!=fa) down=down*mul[v]%mod;
    	ans[u]=fac[n-1]*qpow(down,mod-2)%mod;
    	for(int v:g[u]) if(v!=fa) premul=premul*mul[v]%mod;
    	for(int v:g[u]) if(v!=fa) dfs(v,u,premul*qpow(mul[v],mod-2)%mod*(n-siz[v])%mod);
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1,u,v;i<n;i++){
    		scanf("%d%d",&u,&v);
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	fac[0]=1;
    	for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
    	predfs(1,0);
    	dfs(1,0,1);
    	for(int i=1;i<=n;i++) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Mixly按键控制LED灯(物联网)
    Mixly数码管时钟实验(物联网)
    Java基础语法Day_06(面相对象和封装)
    Java基础语法Day_05(数组的概念)
    Java基础语法Day_02-03(数据类型、运算符、方法、循环结构)
    Java基础语法Day_04
    Java基础语法Day_01
    两个辅助指针变量挖字符串
    玩转多级指针
    二级指针内存模型
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12596776.html
Copyright © 2020-2023  润新知