[B] 熟练剖分(tree)
Posted milk-feng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[B] 熟练剖分(tree)相关的知识,希望对你有一定的参考价值。
题解
首先这个题要明白一个东西:a/b+a/c≡a*(inv[b]+inv[c]) (mod p)。
这个题暴力就可以做。
题目要求期望,那么我们可以求每种可能的概率,然后相乘,就得到期望。
对于每个节点,枚举它的每个儿子作为重链,然后再枚举所有儿子的可能的轻链的条数,更新这个节点。
根据上面的式子,我们可以直接将概率 ”相加“ 而不用通分,
最后在root节点求一下期望。
丑陋的代码:
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #define Maxn 3050 #define mod 1000000007 #define Inv(x) (mi((x),mod-2,mod)) #define Reg register using namespace std; int n,k,root,du[Maxn]; long long p[Maxn][Maxn],vis[Maxn][Maxn]; vector<vector<int> > son(Maxn),vp(Maxn); long long max(long long x,long long y) return x>y?x:y; long long mi(long long x,long long y,long long p) long long ans=1,base=x; while(y) if(y&1) ans=(ans*base)%p; base=(base*base)%p; y>>=1; return ans; void dfp(int x,int child,int zchi,long long cnt,long long poz) if(child==son[x].size()) p[x][cnt]=(p[x][cnt]+poz*Inv(son[x].size()))%mod; if(!vis[x][cnt]) vis[x][cnt]=1; vp[x].push_back(cnt); return; int k=son[x][child]; for(Reg int i=0;i<vp[k].size();++i) if(child!=zchi) dfp(x,child+1,zchi,max(cnt,vp[k][i]+1),(p[k][vp[k][i]]*poz)%mod); else dfp(x,child+1,zchi,max(cnt,vp[k][i]),(p[k][vp[k][i]]*poz)%mod); return; void dfs(int x) // cout<<x<<endl; for(Reg int i=0;i<son[x].size();++i) dfs(son[x][i]); for(Reg int i=0;i<son[x].size();++i) //i是重儿子 概率1/son[x].size() dfp(x,0,i,0,1); if(!son[x].size()) p[x][0]=1; vp[x].push_back(0); vis[x][0]=1; return; int main() // freopen("text.in","r",stdin); scanf("%d",&n); for(Reg int i=1,k;i<=n;++i) scanf("%d",&k); for(Reg int j=1,x;j<=k;++j) scanf("%d",&x); son[i].push_back(x); ++du[x]; for(Reg int i=1;i<=n;++i) if(!du[i]) root=i; dfs(root); long long anp=0; for(Reg int i=0;i<vp[root].size();++i) anp=(anp+p[root][vp[root][i]]*vp[root][i])%mod; printf("%lld",anp); return 0;
以上是关于[B] 熟练剖分(tree)的主要内容,如果未能解决你的问题,请参考以下文章
[Codechef - ADITREE] Adi and the Tree - 树链剖分,线段树
树链剖分2022杭电多校2 1001 Static Query on Tree
树链剖分2022杭电多校2 1001 Static Query on Tree
树链剖分2022杭电多校2 1001 Static Query on Tree