题意:有一棵含有n个结点(n<=300)的根树,树上每个结点上的权值是从[0,ai](ai<=1e9)区间内随机的一个实数,问这棵树能形成一个最小堆的概率。

由于结点取值范围是1e9而且是实数,所以枚举权值dp自然是行不通的了,但可以从函数的角度上考虑。

首先需要了解两个概念:

CDF:分布函数,记为F(x),表示函数F的取值小于等于x的概率。

PDF:概率密度函数,记为f(x),是F(x)的导数,反之,F(x)是f(x)在区间(-∞,x]上的积分。由于本题所有的取值都是从0开始的,因此也可以表示在区间[0,x]上的积分。

那么答案就是根节点rt所对应的CDF的上界Frt(+∞)。

我们记fu(x)为结点u的取值的PDF,Fu(x)为其CDF,那么对于每个叶子结点u来说:

$f_u(x)=\left\{\begin{matrix}\begin{aligned}&\frac{1}{a[u]},0\leqslant x\leqslant a[u]\\&0,others\end{aligned}\end{matrix}\right.,F_u(x)=\int_{0}^{x}f_u(t)dt=\left\{\begin{matrix}\begin{aligned}&\frac{1}{a[u]}x,0\leqslant x\leqslant a[u]\\&1,x>a[u]\end{aligned}\end{matrix}\right.$

那么有了子结点的PDF和CDF,如何去求父结点的PDF和CDF呢?

首先我们要算出每个子结点的取值大于x的概率,因为如果结点u的某个取值x是合法的,那么它的所有子节点的取值都必须大于x。既然Fu(x)表示结点u取值小于等于x的概率,那么取值大于x的概率呢?是1-Fu(x)吗?No!这个公式只适用于叶子结点,因为这里的Fu(x)表示的是“该结点所在子树满足最小堆性质且该结点的值小于等于x的概率”,因此Fu的上界不一定为1,也就是说x的所有取值的概率之和不一定为1。那么应该如何计算呢?

设ub[u]表示结点u及子树下的所有结点的最小的a,那么显然结点u的取值不能超过ub[u],即ub[u]是结点u取值的上界。

所以,正确的计算方法是结点u取值大于x的概率$G_u(x)=\left\{\begin{matrix}\begin{aligned}&F_u(ub[u])-F_u(x),0\leqslant x\leqslant ub[u]\\&0,x>ub[u]\end{aligned}\end{matrix}\right.$

有了子结点的G,就可以求父结点的f了,通过概率计算公式可得:

$f_u(x)=\frac{1}{a[u]}\prod\limits_{fa[v]=u}G_v(x)$

然后对fu(x)积分可以得到Fu(x),然后又可以求出Gu(x),之后就可以继续往父结点递推了。最终答案就是根节点的G(x)的常数项。

复杂度$O(n^3)$

代码如下:(为了方便,代码中每个结点最后保存的函数是G(x))

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+,mod=1e9+;
int hd[N],ne,rt,a[N],n,ub[N];
struct E {int v,nxt;} e[N];
void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
int Pow(int x,int p) {
int ret=;
for(; p; p>>=,x=(ll)x*x%mod)if(p&)ret=(ll)ret*x%mod;
return ret;
}
int inv(int x) {return Pow(x,mod-);}
typedef vector<int> Poly;
Poly F[N];
Poly operator*(Poly& a,Poly& b) {
Poly c(a.size()+b.size()-,);
for(int i=; i<a.size(); ++i)
for(int j=; j<b.size(); ++j)
c[i+j]=(c[i+j]+(ll)a[i]*b[j])%mod;
return c;
}
Poly itg(Poly& a) {
Poly c(a.size()+,);
for(int i=; i<a.size(); ++i)c[i+]=(ll)a[i]*inv(i+)%mod;
return c;
}
int eval(Poly& a,int x) {
int ret=;
for(int i=a.size()-; i>=; --i)ret=((ll)ret*x+a[i])%mod;
return ret;
}
void dfs(int u) {
ub[u]=a[u],F[u].push_back(inv(a[u]));
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
dfs(v),ub[u]=min(ub[u],ub[v]),F[u]=F[u]*F[v];
}
F[u]=itg(F[u]),F[u][]=eval(F[u],ub[u]);
for(int i=; i<F[u].size(); ++i)F[u][i]=-F[u][i];
}
int main() {
memset(hd,-,sizeof hd),ne=;
scanf("%d",&n);
for(int i=,f; i<=n; ++i) {
scanf("%d%d",&a[i],&f);
if(f)addedge(f,i);
else rt=i;
}
dfs(rt);
printf("%d\n",(F[rt][]+mod)%mod);
return ;
}

Kattis - heapsoffun Heaps of Fun (概率密度函数+dp)的更多相关文章

  1. LOJ2267 SDOI2017 龙与地下城 FFT、概率密度函数、Simpson

    传送门 概率论神仙题-- 首先一个暴力做法是设\(f_{i,j}\)表示前\(i\)个骰子摇出点数和为\(j\)的概率,不难发现DP的过程是一个多项式快速幂,FFT优化可以做到\(O(XYlog(XY ...

  2. 【BZOJ-1419】Red is good 概率期望DP

    1419: Red is good Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 660  Solved: 257[Submit][Status][Di ...

  3. rvs产生服从指定分布的随机数 pdf概率密度函数 cdf累计分布函数 ppf 分位点函数

    统计工作中几个常用用法在python统计函数库scipy.stats的使用范例. 正态分布以正态分布的常见需求为例了解scipy.stats的基本使用方法. 1.生成服从指定分布的随机数 norm.r ...

  4. 高斯分布(Gaussian Distribution)的概率密度函数(probability density function)

    高斯分布(Gaussian Distribution)的概率密度函数(probability density function) 对应于numpy中: numpy.random.normal(loc= ...

  5. 【bzoj4832】[Lydsy2017年4月月赛]抵制克苏恩 概率期望dp

    题目描述 你分别有a.b.c个血量为1.2.3的奴隶主,假设英雄血量无限,问:如果对面下出一个K点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输入 输入包含多局游戏. 第一行包含一个整数 T (T ...

  6. 【loj6191】「美团 CodeM 复赛」配对游戏 概率期望dp

    题目描述 n次向一个栈中加入0或1中随机1个,如果一次加入0时栈顶元素为1,则将这两个元素弹栈.问最终栈中元素个数的期望是多少. 输入 一行一个正整数 n . 输出 一行一个实数,表示期望剩下的人数, ...

  7. 函数的光滑化或正则化 卷积 应用 两个统计独立变量X与Y的和的概率密度函数是X与Y的概率密度函数的卷积

    http://graphics.stanford.edu/courses/cs178/applets/convolution.html Convolution is an operation on t ...

  8. BZOJ_3566_[SHOI2014]概率充电器_概率+树形DP

    BZOJ_3566_[SHOI2014]概率充电器_概率+树形DP Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器: “采用全新纳米级加工技 ...

  9. Codeforces - 1264C - Beautiful Mirrors with queries - 概率期望dp

    一道挺难的概率期望dp,花了很长时间才学会div2的E怎么做,但这道题是另一种设法. https://codeforces.com/contest/1264/problem/C 要设为 \(dp_i\ ...

随机推荐

  1. Day01:文件操作(File、RandomAccessFile)

    文件操作 JAVA中的 File 类是文件和目录路径名的抽象形式.使用 File 类可以获取文件本身的一些信息,例如文件所在的目录.文件长度.文件读写权限等. 在 Java 中,File 类是 jav ...

  2. Unity中的动画系统和Timeline(2) 按钮动画和2D精灵动画

    按钮动画 1 创建按钮后,按钮的Button组件中,Transition我们平时用的时Tint,这次选择Animation 选择Auto Generate Animation,创建一个按钮动画 2 后 ...

  3. OpenStack组件——cinder存储服务

    1.cinder 介绍 1)理解 Block Storage 操作系统获得存储空间的方式一般有两种: (1)通过某种协议(SAS,SCSI,SAN,iSCSI 等)挂接裸硬盘,然后分区.格式化.创建文 ...

  4. cisco路由的ip静态路由添加(二)

    路由器Corp 配置Corp(config)#ip route 192.168.20.0 255.255.255.0 10.1.3.2 150 Corp(config)#ip route 192.16 ...

  5. elastic mapping not_analyzed 简单理解 + analysis-ik分词器安装

    1.索引index ,这个参数可以控制字段应该怎样建索引,怎样查询.它有以下三个可用值: not_analyzed:将字段的原始值放入索引中,作为一个独立的term,它是除string字段以外的所有字 ...

  6. 解决android studio的Gradle一直在sync的办法

    出现问题的原因就是gradle下载太慢了. 打开gradle-wrapper.properties文件.查看gradle版本.如下: distributionUrl=https\://services ...

  7. hello1的web.xml解析

    <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" ...

  8. C++练习 | 单向链表类模板(包含类模板中静态变量初始化格式)

    #include <iostream> #include <string> using namespace std; template <class T> clas ...

  9. 如何在LinuxKernel中操作file(set_fs與get_fs)

    在Kernel 中,照理說能存取至 0 ~ 4GB.但是實作層面卻是只能讓我們使用到3GB ~ 4GB 這會導致我們無法使用open(),write()這些在user space下的function. ...

  10. css简单动画(transition属性)

    一.对transition属性的认识 1.transition 属性是一个简写属性,可用于设置四个过渡属性:transition-property     过渡效果的 CSS 属性的名称(height ...