【题解】Heaps of Fun (概率论)
【题解】Heaps of Fun (概率论)
看完题解才发现讲题的时候讲的是什么屎,你说的分段是指分两段吗.......
简要题意:
给定你一棵树(不一定是二叉树),每个点有个随机点权,在\([0,a[u]]\)均匀分布,问你这棵树满足堆性质(小根堆)的概率是多少?
取值如果是整数可以直接DP,但是如果是实数怎么办?
每个节点搞一个随机变量\(X_u\),满足\(P(X_u=x)\)表示这个节点是\(x\)的时候的满足条件的概率,概率分布函数和概率密度函数分别记为\(F_u(x),f_u(x)\),定义查百度,特别提醒\(F_u(x)=\sum_{t\le x} P(X_u=t)\)是前缀,而\(\int f(x)\mathrm dx=F(x)+0\)
边界条件很好办,不论咋样都是合法的,但是怎么转移呢??
假若\(X_u=x\),那么如果要合法,就要保证\(X_{son[u]}< x\),而这个概率就是\(F_{son[u]}(x)\)(因为概率分布函数是连续的),所以
\[P(X_u=x)={1\over a[u]}\prod_{v\in son[u]} P(X_v>x)
\]
但是\(X\)是连续的随机变量,我们只能通过\(F,f\)来转移。设\(low[x]\)表示\(x\)子树内最小的\(a[u]\)值,那么这个值是最小满足条件(合法且在定义域内)的值(实际上取不到,只能无限接近),所以\(P(X_x>t)=F(low[x])-F(t)\)。设\(=h_u(x)\)
根据一些前置姿势(概率论与数理统计上有),\(f_x(t)=P(X_x=t)\),根据书上的关系就有\(F(x)=\int f(x)\),那么直接积分一下就好了
答案是\(h_{rt}(+\inf)=F_{rt}[0]\)
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std; typedef long long ll;
inline int qr(){
int ret=0,f=0,c=getchar();
while(!isdigit(c))f|=c==45,c=getchar();
while(isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
typedef vector<int> poly;
const int mod=1e9+7;
const int maxn=3e2+5;
poly f[maxn],e[maxn];
int low[maxn],a[maxn],n,rt;
int MOD(const int&x){return x>=mod?x-mod:x;}
int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
poly operator * (poly a,poly b){
if(a.empty()||b.empty()) return poly();
poly ret(a.size()+b.size()-1,0);
for(int t=0,ed=a.size();t<ed;++t)
for(int i=0,ed=b.size();i<ed;++i)
ret[t+i]=MOD(ret[t+i]+MOD(a[t],b[i]));
return ret;
}
int ksm(const int&ba,const int&p){
int ret=1;
for(int t=p,b=ba;t;t>>=1,b=1ll*b*b%mod)
if(t&1) ret=1ll*ret*b%mod;
return ret;
}
void Int(poly&x){
if(x.empty()) return;
x.resize(x.size()+1);
for(int t=x.size()-1;t;--t)
x[t]=MOD(x[t-1],ksm(t,mod-2));
x[0]=0;
}
int F(const poly&x,int g){
int ret=0;
for(int t=x.size()-1;~t;--t)
ret=MOD(MOD(ret,g)+x[t]);
return ret;
}
void add(int fr,int to){e[fr].push_back(to);}
void dfs(int now){
low[now]=a[now]; f[now].resize(1,1);
for(auto t:e[now])
dfs(t),low[now]=min(low[now],low[t]),f[now]=f[now]*f[t];
f[now]=f[now]*(poly){ksm(a[now],mod-2)};
Int(f[now]); f[now][0]=F(f[now],low[now]);
for(int t=1,ed=f[now].size();t<ed;++t) f[now][t]=MOD(mod-f[now][t]);
}
int main(){
n=qr();
for(int t=1;t<=n;++t){
a[t]=qr();
int fa=qr();
if(fa) add(fa,t);
else rt=t;
}
dfs(rt);
printf("%d\n",f[rt][0]);
return 0;
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!