真的是一道很有意思的题目
实际上,这道题与换根没啥关系,主要是与二次扫描有点关系
1. 前置知识简单讲解
1.1. 关于问题本身
输出一行一个实数,为进入充电状态的元件个数的期望,四舍五入到六位小数。
什么是期望?(以下只是这个蒟蒻自学后所总结的,显然不会很严谨)
现在有 nnn 个事件,每个事件发生的概率为 ppp,期望值为 sss,那么最终的期望值为:
∑i=1npisi\sum\limits_{i=1}^np_is_ii=1∑npisi
看不懂?举个例子:
你要投一个骰子,求:的所得到的点数的期望
显然,有 666 个事件,它们发生的概率都是 16\dfrac{1}{6}61,而每一个事件的期望值分别为 1,2,3,4,5,61,2,3,4,5,61,2,3,4,5,6(骰子的 666 个点数),则最终的期望为 16×(1+2+3+4+5+6)=3\dfrac{1}{6}\times(1+2+3+4+5+6)=361×(1+2+3+4+5+6)=3
而对于本问题,事件就是元件是否进入充电状态,期望值为 111(充起了就会使充起的数量 +1+1+1),那么,我们只需要将所有元件进入充电状态的可能性相加即可。
1.2. 有关概率
先掏出结论:
对于两个相互独立的事件 A,BA,BA,B,它们的概率分别为 a,ba,ba,b,则:事件 A,BA,BA,B 至少发生一个的概率为 a+b−aba+b-aba+b−ab
证明显然:
- AAA 发生,BBB 不发生的概率:a(1−b)a(1-b)a(1−b)
- BBB 发生,AAA 不发生的概率:b(1−a)b(1-a)b(1−a)
- A,BA,BA,B 都发生:ababab
把它们加起来:a(1−b)+b(1−a)+ab=a+b−aba(1-b)+b(1-a)+ab=a+b-aba(1−b)+b(1−a)+ab=a+b−ab
这是一个极为重要的结论,后面会多次使用
2. 题解时间
对于一个元件 iii,想要使它充上电,无非三种情况
- 自己给自己来电(
劲啊) - 儿子给自己来电(
How 孝顺 the son is!) - 祖先或祖先的其它儿子来电
考虑到祖先,自己,儿子之间会互相影响,有点麻烦,所以,我们首先只考虑情况 111 和情况 222
我们设dp[x]
用来表示第 xxx 个元件充上电的概率,显然,情况 111 的概率为 a[x]/100
,情况 222 的概率为 dp[y]*z
(y
代表x
的一个儿子,z
表示连接这两个元件的导线的充电概率)
也很显然,要么只有情况 111 影响 dp[x]
,要么只有情况 222 影响 dp[x]
,要么情况 111 和情况 222 都影响 dp[x]
,两个事件至少发生一个,按照上面的公式,我们可以得到在只考虑情况 111 和情况 222 的情况下的dp[i]
代码:
void dfs(int x,int fa){
for(int i=head[x];i;i=Next[i]){
int y=ver[i];
double z=edge[i];
if(y^fa){
dfs(y,x);
dp[x]=dp[x]+dp[y]*z-dp[x]*dp[y]*z;//套公式
//这里,我将 a[x] 的值直接输入到 dp[x] 里面去了
}
}
}
接下来,考虑加入情况 333
我们只考虑父亲转移儿子
对于 xxx 元件的父亲 fff,它的转移情况有两种
A. 不是由 xxx 元件转移而来(设其概率为 aaa)
B. 是由 xxx 元件转移而来(设其概率为 bbb)
(这里为了区分前面的 1,2,31,2,31,2,3,使用了 A,B
)
显然,如果要让 fff 来影响 xxx,那么,xxx 就不能影响 fff(你丫的搁这儿搁这儿呢)
若连接 f,xf,xf,x 元件的导线的充电概率为 zzz,那么,情况 333 的概率实际上应为 a*z
思考:aaa 的求法
首先,不难看出,b
应该等于dp[x]*z
,那么,求a
就不难了
由于,要么只有情况A
影响dp[f]
,要么只有情况B
影响dp[f]
,要么情况A
和情况B
都影响了dp[f]
,所以,套公式:a+dp[x]*z-a*dp[x]*z=dp[f]
把a
求出来之后,就可以将情况 333 代入了
但是注意,最终求出来的a
是一个分数的形式,而分母是有可能为 000 的,注意特判
代码:
void DP(int x,int fa){
for(int i=head[x];i;i=Next[i]){
int y=ver[i];
double z=edge[i];
if(y^fa){
if(dp[y]*z<=1+0.00000001&&dp[y]*z>=1-0.00000001){//判0,注意精度
DP(y,x);
continue;
}
double tot=(dp[x]-dp[y]*z)/(1-dp[y]*z);//套公式
dp[y]=dp[y]+tot*z-dp[y]*tot*z;
DP(y,x);
}
}
}
3. 代码时间
404 Not Found
实际上,我甚至连两个关键函数都给你了,还有什么必要看完整代码吗?