题意
一棵树,每个点有个取值范围,随机取值(实数),最后树是一个小根堆的概率
题解
取值范围是很大的,无法枚举,这个时候:
我们可以把
f
u
(
x
)
f_u(x)
fu(x)定义成:
u
u
u的子树合法且
u
u
u取
x
x
x的概率(准确说是概率密度);
f
u
(
x
)
=
1
b
u
f_u(x)=\frac{1}{b_u}
fu(x)=bu1[叶子节点]
这个是无法直接做的,我们考虑概率分布函数 F u ( x ) = ∫ f u ( x ) F_u(x)=\int f_u(x) Fu(x)=∫fu(x),表示的是 u u u的子树合法且 u u u取值 ≤ x \leq x ≤x的概率。
知道这个其实就可以尝试做了,但是由于还是有 x x x,而且 x x x显然是较大的,并且主要是通过 f u f_u fu和 F u ( x ) F_u(x) Fu(x)无法得知如何从孩子节点的状态转移过来(快速转移), u u u点 ≤ x \leq x ≤x,子树并不知道是多少。
这个时候我们再定义一个函数
G
u
(
x
)
G_u(x)
Gu(x):表示合法且
u
≥
x
u\geq x
u≥x的概率。
G
u
(
x
)
=
F
u
(
b
u
)
−
F
u
(
x
)
G_u(x)=F_u(b_u)-F_u(x)
Gu(x)=Fu(bu)−Fu(x).
显然有:
f
u
(
x
)
=
1
b
u
∗
∏
G
s
o
n
(
x
)
f_u(x)=\frac{1}{b_u}*\prod G_{son}(x)
fu(x)=bu1∗∏Gson(x)保证孩子节点都比
f
u
f_u
fu大
最后结果是
G
r
o
o
t
(
0
)
G_{root}(0)
Groot(0).
注意一个细节,我们计算的时候
x
x
x不应该超过下面的最小(最大值),否则会出现错误,所以我们先计算出
f
u
(
x
)
→
F
u
(
x
)
f_u(x)\to F_u(x)
fu(x)→Fu(x),计算
G
u
(
x
)
G_u(x)
Gu(x)的时候,要考虑
x
≤
min
(
max
)
x \leq \min(\max)
x≤min(max),因为这个时候需要代值,其他时候可以直接计算多项式,而不是先代值,这样就会比较简单。
显然这些函数都是多项式(积分得到的),所以模拟多项式即可。
int n,a[maxn],b[maxn];
int inv[maxn];
vector<int>G[maxn];
//inv[0]=inv[1]=1;
//for(int i=2;i<=300;++i) inv[i]=mul(mod-mod/i,inv[mod%i]);
struct poly{
int a[maxn],deg;
poly(){memset(a,0,sizeof(a));}
poly(int x){memset(a,0,sizeof a),a[0]=x,deg=1;}
int&operator[](int x){return a[x];}
void inc(int&a,int b){a+=b-mod,a+=a>>31&mod;}//*2
};
void inc(int&a,int b){a+=b-mod,a+=a>>31&mod;}
int sub(int a,int b){return a-=b,a+(a>>31&mod);}
int mul(int a,int b){return 1ll*a*b%mod;}
int pow(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
poly sub(poly f,poly g){
poly h;h.deg=std::max(f.deg,g.deg);
for(int i=0;i<h.deg;++i) h[i]=sub(f[i],g[i]);
return h;
}
poly Int(poly f){
poly g;g.deg=f.deg+1;
for(int i=0;i<f.deg;++i) g[i+1]=mul(f[i],inv[i+1]);
return g;
}
poly mul(poly f,poly g){
poly h;h.deg=f.deg+g.deg-1;
for(int i=0;i<f.deg;++i) for(int j=0;j<g.deg;++j) inc(h[i+j],mul(f[i],g[j]));
return h;
}
int cal(poly f,int x){
int s=0;
for(int i=0,t=1;i<f.deg;++i,t=mul(t,x)) inc(s,mul(t,f[i]));
return s;
}
poly dfs(int u,int f){
poly res=poly(pow(b[u],mod-2));
a[u]=b[u];
for(int i=0,v;i<G[u].size();i++){
v=G[u][i];
if(v==f)continue;
res=mul(res,dfs(v,u));//求fu
a[u]=min(a[u],a[v]);
}
res=Int(res);//求Fu
res=sub(poly(cal(res,a[u])),res);
return res;
}