Codeforces 802L Send the Fool Further! (hard)

Description

题面
题目大意:求从根节点出发,每次随机走一个相邻的点,问走到任意一个叶子节点经过的路径长度的期望(走到就停止)

Solution

树上高斯消元,复杂度是 \(O(n)\)
\(f[x]\) 表示从 \(x\) 走到任意一个叶子节点路径长度的期望
首先列出转移方程: \(f[x]=\frac{f[fa]+dis(x,fa)+\sum f[son]+dis(x,son)}{in[x]}\)
对于叶子节点 \(f[x]=0\)
对于叶子的父亲只有 \(f[x]\)\(f[fa]\) 两个未知项,我们可以直接把 \(f[x]\) 代入到父亲的方程中
从而使得父亲的方程也只有两个未知数,一直推到根节点,而根节点没有父亲,直接拿常数项除以系数就是答案

#include
using namespace std;
const int N=1e5+10,mod=1e9+7;
int head[N],nxt[N<<1],to[N<<1],num=0,n,b[N],fa[N],q[N],DFN=0,k[N],in[N];
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
inline int qm(int x,int k){
    int sum=1;
    while(k){
        if(k&1)sum=1ll*sum*x%mod;
        x=1ll*x*x%mod;k>>=1;
    }
    return sum;
}
inline int inv(int x){return qm(x,mod-2);}
inline void dfs(int x,int last){
    q[++DFN]=x;
    for(int i=head[x];i;i=nxt[i])
        if(to[i]!=last)fa[to[i]]=x,dfs(to[i],x);
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  int x,y,z;
  scanf("%d",&n);
  for(int i=1;i=1;i--){
      int x=q[i];
      if(in[x]==1)continue;
      k[fa[x]]=(k[fa[x]]-inv(k[x]))%mod;
      b[fa[x]]=(b[fa[x]]+1ll*inv(k[x])*b[x])%mod;
  }
  b[1]=1ll*b[1]*inv(k[1])%mod;
  if(b[1]<0)b[1]+=mod;
  printf("%d\n",b[1]);
  return 0;
}

转载于:https://www.cnblogs.com/Yuzao/p/8478111.html

你可能感兴趣的:(Codeforces 802L Send the Fool Further! (hard))