题意:有一棵含有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. 让nginx 的ssi支持include相对路径

    好久没接触nginx了,今天帮同事解决一个客户的问题,顺便记录下:version : nginx-1.6.2问题描述:客户的files.shtml里面include一个网站的头部文件( <!–# ...

  2. 致远OA利用POC

    批量检测url 在脚本同目录下建立url.txt 放入待检测的URL 运行脚本 # Wednesday, 26 June 2019 # Author:nianhua # Blog:https://gi ...

  3. python笔记之元祖

    元祖创建使用圆括号括起来,中间元素使用逗号隔开 如:tuple1 = (1,2,3,4) tuple2 = () 空元祖 #!/usr/bin/env python #-*-coding:utf-8- ...

  4. XML 基本概念和XPath选择

    books.xml文件 <?xml version="1.0" encoding="ISO-8859-1"?> <bookstore> ...

  5. 简单nginx代理配置

    nginx.conf: # For more information on configuration, see:# * Official English Documentation: http:// ...

  6. UOJ46 玄学

    题目 一个比较自然的想法是线段树维护二进制分组. 因为我们询问的是一段连续的操作的积,所以我们可以建一棵线段树,每个节点存储当前区间各个操作的积. 这里的操作的积指的是把一系列操作做完之后区间每个位置 ...

  7. # vmware异常关机后,虚拟系统无法启动的解决办法

    vmware异常关机后,虚拟系统无法启动的解决办法 先使用everything搜索所有后缀为.lck的文件,这些文件全部删除,如果不确定是否可以删除,先把这些文件转移到桌面,等能启动虚拟系统之后再删除 ...

  8. WPF ListView多行显示

    //前台 <ListView Margin="14,152,12,74" Name="lvList" SelectionMode="Multip ...

  9. Python爬虫之简单爬虫框架实现

    简单爬虫框架实现 目录 框架流程 调度器url管理器 网页下载器 网页解析器 数据处理器 具体演示效果 框架流程 调度器 #导入模块 import Url_Manager import parser_ ...

  10. selenium 模拟登陆豆瓣,爬取武林外传的短评

    selenium 模拟登陆豆瓣,爬去武林外传的短评: 在最开始写爬虫的时候,抓取豆瓣评论,我们从F12里面是可以直接发现接口的,但是最近豆瓣更新,数据是JS异步加载的,所以没有找到合适的方法爬去,于是 ...