luoguP4284 [SHOI2014]概率充电器 概率期望树形DP
这是一道告诉我概率没有想象中那么难的题.....
首先,用期望的线性性质,那么答案为所有点有电的概率和
发现一个点的有电的概率来源形成了一个"或"关系,在概率中,这并不好计算...(其实是可以算的,只不过式子要复杂点...)
考虑反面,一个点没电的概率来源是一个“与”关系,比较好计算
举个荔枝,有$A, B, C$三个变量,$A, B, C$分别有$0.5, 0.3, 0.2$的概率为$1$
问$A | B | C$为$1$的概率?
如果,我们从正面考虑,那么答案为$0.5 + (1 - 0.5) * 0.3 + (1 - 0.5 - (1 - 0.5) * 0.3) * 0.2 = 0.72$
但是,如果从反面考虑,那么答案为$1 - (1 - 0.2)(1 - 0.3)(1 - 0.5) = 0.72$
从这个荔枝可以看出,概率中“或”很难算,“与”比较好算(其实求解$| = !\&!$)
那么,考虑一个点没电,大体上分为子树不给电和父亲不给电两种情况
分别来考虑:
记$i$自己用爱发电的概率为$e_i$,边$(u, v)$用爱发电的概率为$e(u, v)$
设子树内不给$u$充电的概率为$f[u]$,那么$f[u] = (1 - e_i) * \prod_{v \in son_u} f[v] + (1 - f[v]) * (1 - e(u, v))$
再来考虑父亲不给电
设父亲不给$u$充电的为$g[u]$,那么有$g[u] = g[fa] + (1 - g[fa])(1 - e(u, fa))$
那么,求解$g[fa]$就成了一个问题,如果我们在$O(n ^2 )$的时间内求出所有的$g[fa]$,那么我们就能在$O(n ^ 2)$求出所有的$f$
在$O(n ^ 2)$的时间内求出$g[fa]$,自然是不难的,发现这是一个以$fa$为根的$dp$
对于一个节点,$f[u] *g[u]$就是答案
进一步分析,发现其实求$g[fa]$的时候非常的状态是重复的,能不能优化呢?
当然是可以的,画个美妙的图
那么,注意到以$fa$为根的子树包括$gf$的子树和$fa$除了$u$以外的子树
那么,只要能快速地调用除了$u$以外的所有子树转移值得乘积,就能解决左边的子树
同时,右边的子树可以调用$g[gf]$来快速转移
然后就是$O(n)$啦!
代码好像还加了点优化
年代久远了,忘了是什么优化了...
#include <cstdio>
#define dl double
#define sid 500050
#define ri register int
using namespace std; char RR[];
extern inline char gc() {
static char *S = RR + , *T = RR + ;
if(S == T) fread(RR, , , stdin), S = RR;
return *S ++;
}
inline int read() {
int p = , w = ; char c = gc();
while(c > '' || c < '') { if(c == '-') w = -; c = gc(); }
while(c >= '' && c <= '') { p = p * + c - ''; c = gc(); }
return p * w;
} int n, cnt;
dl a[sid], s[sid], f[sid], pi[sid * ];
int cap[sid], node[sid * ], nxt[sid * ]; void addedge(int u, int v, dl p) {
nxt[++ cnt] = cap[u]; cap[u] = cnt;
node[cnt] = v; pi[cnt] = 1.0 - p;
} void son_fa(int e, int fa) {
s[e] = - a[e];
for(int i = cap[e]; i; i = nxt[i]) {
int d = node[i];
if(fa == d) continue;
son_fa(d, e);
s[e] *= s[d] + ( - s[d]) * pi[i];
}
} void fa_son(int e, int fa) {
for(int i = cap[e]; i; i = nxt[i]) {
int d = node[i];
if(d == fa) continue;
dl P = f[e] / (s[d] + ( - s[d]) * pi[i]);
f[d] = (P + ( - P) * pi[i]) * s[d];
fa_son(d, e);
}
} int main() {
n = read();
for(ri i = ; i < n; i ++) {
int u = read(), v = read(), p = read();
addedge(u, v, p / 100.0); addedge(v, u, p / 100.0);
}
for(ri i = ; i <= n; i ++) {
int p = read();
a[i] = p / 100.0;
}
son_fa(, );
f[] = s[];
fa_son(, );
dl ans = ;
for(ri i = ; i <= n; i ++) ans += - f[i];
printf("%.6lf\n", ans);
return ;
}
luoguP4284 [SHOI2014]概率充电器 概率期望树形DP的更多相关文章
- [BZOJ3566][SHOI2014]概率充电器 换根树形DP
链接 题意:n个充电元件形成一棵树,每个点和每条边都有各自的充电概率,元件可以自身充电或者通过其他点和边间接充电,求充电状态元件的期望个数 题解 设1为根节点 设 \(f[x]\) 表示 \(x\) ...
- 洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP
洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP 题目描述 著名的电子产品品牌\(SHOI\) 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米 ...
- 【BZOJ3566】[SHOI2014]概率充电器 期望+树形DP
[BZOJ3566][SHOI2014]概率充电器 Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:“采用全新纳米级加工技术,实现元件与导线 ...
- [BZOJ3566][SHOI2014]概率充电器(概率DP)
题意:树上每个点有概率有电,每条边有概率导电,求每个点能被通到电的概率. 较为套路但不好想的概率DP. 树形DP肯定先只考虑子树,自然的想法是f[i]表示i在只考虑i子树时,能有电的概率,但发现无法转 ...
- 【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP
好久没有写过题解了--现在感觉以前的题解弱爆了,还有这么多访问量-- 没有考虑别人的感受,没有放描述.代码,题解也写得歪歪扭扭. 并且我要强烈谴责某些写题解的代码不打注释的人,像天书那样,不是写给普通 ...
- luogu P3412 仓鼠找sugar II 期望 树形dp
LINK:仓鼠找sugar II 以前做过类似的期望题目 加上最后的树形dp不算太难 还是可以推出来的. 容易发现 当固定起点和终点的时候 可以先固定根 这样就不用分到底是正着走还是倒着走了. 1为根 ...
- bzoj 3566: [SHOI2014]概率充电器 数学期望+换根dp
题意:给定一颗树,树上每个点通电概率为 $q[i]$%,每条边通电的概率为 $p[i]$%,求期望充入电的点的个数. 期望在任何时候都具有线性性,所以可以分别求每个点通电的概率(这种情况下期望=概率 ...
- BZOJ.3566.[SHOI2014]概率充电器(概率DP 树形DP)
BZOJ 洛谷 这里写的不错,虽然基本还是自己看转移... 每个点的贡献都是\(1\),所以直接求每个点通电的概率\(F_i\),答案就是\(\sum F_i\). 把\(F_x\)分成:父节点通电给 ...
- [JZOJ 5911] [NOIP2018模拟10.18] Travel 解题报告 (期望+树形DP)
题目链接: http://172.16.0.132/senior/#contest/show/2530/1 题目: EZ同学家里非常富有,但又极其的谦虚,说话又好听,是个不可多得的人才. ...
随机推荐
- js中不能做变量名的字符
JavaScript中不能作为变量名的关键字和保留字总结: 1.js中的关键字: break case catch continue default delete do else finally fo ...
- 一款已上市MMO手游地图同步方案总结
1. 客户端地图格子的相关知识 在2.5D的MMO游戏里,角色是通过3D的方式渲染,2D的地图是通过2D的方式显示,所以在客户端一般会有三个坐标系: a) 3D坐标系:所有需要3D渲染的角色和光效,都 ...
- python基础===数据伪造模块faker
介绍文档: https://pypi.org/project/Faker/ https://faker.readthedocs.io/en/latest/ https://faker.readthed ...
- 生成器(generator)和迭代(iterable , iterator, iteration)
在搞清楚Generator之前,我们先讨论一下 iterable , iterator, iteration 1.Iterable 我们知道,在Python中所有东西都是object, 比如说变量,容 ...
- fsarchiver创建系统镜像(dd命令也可以)
fsarchiver简介 fsarchiver可以将整个文件系统的内容保存成一个压缩形式的归档文件,包含文件系统本身.所以用来做系统镜像是一个不错的选择,一旦系统崩溃但可以进入救援模式,我们就可以使用 ...
- gbdt和xgboost中feature importance的获取
来源于stack overflow,其实就是计算每个特征对于降低特征不纯度的贡献了多少,降低越多的,说明feature越重要 I'll use the sklearn code, as it is g ...
- Linux创建ftp并设置权限以及忘记ftp帐号(密码)修改
忘记ftp密码修改方法: 1.登录服务器 cd /etc/vsftpdcat ftpusers找到对应的ftp用户名 (如果用户名也忘记了 那么 cd /etc 然后cat passwd 查看用户和 ...
- 查找网页元素对应的js代码
按F12打开调试窗口,切换到Sources选项卡,最右边的Event Listener Breakpoints里勾选Mouse下的mouseover即可,当鼠标移动到图片上时触发mouseover事件 ...
- golang基础之二-基本数据类型和操作符
文件名&关键字&标识符 所有go源码都是以.go结尾 标识符以字母或下划线开头,大小写敏感 下划线_是特殊标识符,用户忽略结果 保留关键字 导入包时可以设置别名 下面是保留关键字: b ...
- JAVA实现图的邻接表以及DFS
一:定义邻接表结构储存图 package 图的遍历; //邻接表实现图的建立 //储存边 class EdgeNode { int index; // 习惯了用index,其实标准写法是(adjVer ...