码迷,mamicode.com
首页 > 其他好文 > 详细

[B] 熟练剖分(tree)

时间:2019-07-15 12:08:58      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:ide   图片   show   open   直接   代码   long   ==   text   

题解

首先这个题要明白一个东西: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)

标签:ide   图片   show   open   直接   代码   long   ==   text   

原文地址:https://www.cnblogs.com/Milk-Feng/p/11187965.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!