题:https://atcoder.jp/contests/abc160/tasks/abc160_f
题意:给定一棵树,问以每个节点为开始的拓扑排序有多少个;
分析:全部的情况为n!,那么得在其中挑选出合法的,因为要求拓扑排序,所以要求根要为第一个节点,所以是从sz[u]选出1个方案,即乘上C(sz[u],1),对于递归下去的每个节点也时这种情况。所以真正要维护的就是size的前缀积既可。
#include<bits/stdc++.h> using namespace std; #define lson root<<1,l,midd #define rson root<<1|1,midd+1,r #define pb push_back typedef long long ll; const int M=1e6+6; const int mod=1e9+7; vector<int>g[M]; ll facn=1; int n; ll ans[M],sz[M],mul[M],fac[M]; ll ksm(ll a,ll b){ a%=mod; ll t=1; while(b){ if(b&1) t=t*a%mod; a=a*a%mod; b>>=1; } return t; } void dfs1(int u,int fa){ sz[u]=mul[u]=1; for(auto v:g[u]){ if(v!=fa){ dfs1(v,u); sz[u]+=sz[v]; mul[u]=mul[u]*mul[v]%mod; } } mul[u]=mul[u]*sz[u]%mod; } void dfs2(int u,int fa,ll last){ ll tmp=last; for(auto v:g[u]) if(v!=fa) tmp*=mul[v],tmp%=mod; ans[u]=facn*ksm(tmp,mod-2)%mod; for(auto v:g[u]) if(v!=fa) last*=mul[v],last%=mod; for(auto v:g[u]) if(v!=fa) dfs2(v,u,last*ksm(mul[v],mod-2)%mod*(n-sz[v])%mod); } int main(){ scanf("%d",&n); for(ll i=2;i<n;i++) facn*=i,facn%=mod; for(int u,v,i=1;i<n;i++){ scanf("%d%d",&u,&v); g[u].pb(v); g[v].pb(u); } dfs1(1,0); dfs2(1,0,1); for(int i=1;i<=n;i++) printf("%lld ",ans[i]); return 0; }