[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;
View Code

 

以上是关于[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

CF725GMessages on a Tree 树链剖分+线段树

poj 3237 Tree(树链剖分,线段树)