思路
应该是个比较基础的换根吧...我相信我再做几个换根应该都能做出来的!
令表示这个节点的联通点集的数量.
那么一个很显然的一个方程就是其中是的子节点.这个点的联通点集数量就是子节点的联通点集数量的选取,以及不选取的方案数的乘积.
由此我们可以的算出一个点的答案是多少.
然后考虑换根,的子节点的答案怎么算呢?其实挺简单的,思考变成的子节点,以前的是不是会少了这个点的答案呢?所以当然这不够,考虑已经成为了根节点,那么不含这部分的值是拿这个值即可.
对于为的没有逆元,这时暴力算即可.
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+5; const int mod=1e9+7; ll dp[N],ans[N]; vector<int>g[N]; ll qp(ll a,ll b) { ll res=1; while(b) { if(b&1) res=res*a%mod; a=a*a%mod; b>>=1; } return res; } void dfs(int u,int fa) { dp[u]=1; for(int v:g[u]) { if(v==fa) continue; dfs(v,u); dp[u]=dp[u]*(dp[v]+1)%mod; } } void DFS(int u,int fa) { if(fa==-1) ans[u]=dp[u]; else if((dp[u]+1)%mod==0) { dfs(u,u); ans[u]=dp[u]; } else ans[u]=(ans[fa]%mod*qp(dp[u]+1,mod-2)+1)%mod*(dp[u])%mod; for(int v:g[u]) { if(v==fa) continue; DFS(v,u); } } int main() { int n; scanf("%d",&n); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } dfs(1,1); DFS(1,-1); for(int i=1;i<=n;i++) printf("%lld\n",ans[i]); return 0; }