分析:
啊咧,为什么标签都是dp唉?
但是前辈都吐槽这道题根本不是dp啊。。。
前辈说有一个
O(n2h)
O
(
n
2
h
)
的dp(只针对已知Alice求Bob),xue微想了一下:
f[i][k]
f
[
i
]
[
k
]
表示到第i栋楼,ta的高度为k时Bob计数器的期望
枚举与i连接的建筑物j,显然j~i之间不会有楼高于k,概率为:
(k−1)xhx,x=i−j−1
(
k
−
1
)
x
h
x
,
x
=
i
−
j
−
1
(因为Bob根本不可能到达h以上的高度,我们不用考虑)
显然这个dp一点用都没有(博主有毛病啊)
正解
我们还是由浅到深
Bob->Alice
首先我们观察一下样例
啊咧,为什么输出的是一个整数不是real类型啊,好像有猫腻(不像是算出来的,倒像是读入后世界输出的)
实际上,找到AC代码试一下,发现确实是输入什么输出什么啊
不要向某人一样投机取巧,我们是可以证明:
Bob的计数器累加了 2i 2 i ,那么ta所经过的楼的期望数目也是 2i 2 i
不严谨证明:
显然,Bob每使用一次ZIP运输线,实际上经过的楼数是:在运输线下高度较小的楼+终点楼
也就是说,如果ta经过了
i
i
栋楼,那么就有栋高度较小的楼在之间
设Bob当前计数器增加了
2H
2
H
,那么ta就在第
H
H
层楼上
然而由于这个zz的编号方式,第层楼的高度实际上是
H+1
H
+
1
那么ta经过的楼的高度就不会超过
H
H
经过楼的期望=
+2∗P(中间有一栋楼,高度≤H)∗P(终点楼的高度≥H)
+
2
∗
P
(
中
间
有
一
栋
楼
,
高
度
≤
H
)
∗
P
(
终
点
楼
的
高
度
≥
H
)
+∗P(中间有两栋楼,高度≤H)∗P(终点楼的高度≥H)+...
+
∗
P
(
中
间
有
两
栋
楼
,
高
度
≤
H
)
∗
P
(
终
点
楼
的
高
度
≥
H
)
+
.
.
.
(
P
P
表示概率)
题目中给出,高度为的楼出现的概率是 2−i=(12)i 2 − i = ( 1 2 ) i
因此,一栋楼的高度 ≤H ≤ H 的概率:
期望:
混合等差等比数列,错位相消:
①-②,得:
其中, P=2H−12H P = 2 H − 1 2 H
Alice->Bob
首先我们假设所有的楼都只有一层,编号都是0
这种情况下,Bod的计数器得到的一定是
n
n
之后我们要加上一些高度更高的楼层,这样楼层之间就会出现一些ZIP运输线
此时,Bob计数器的答案就应该+运输线的贡献-覆盖掉的楼的贡献
我们一层一层的把楼加高,对于新加入的编号能达到的楼
这两栋楼的编号分别为
i,j
i
,
j
,设
L=j−i
L
=
j
−
i
,如果这两栋楼的第
H
H
层之间有运输线
那么一定满足:和
j
j
的高度,
i−j
i
−
j
之间的楼的高度
小于等于H
小
于
等
于
H
之前我们已经求出一栋楼的高度
≤H
≤
H
的概率:
P=2H−12H
P
=
2
H
−
1
2
H
显然,一栋楼的高度
≥H+1
≥
H
+
1
的概率:
1−P=12H
1
−
P
=
1
2
H
因此,两栋楼层编号能够达到 H H 的楼中间存在一条运输线的概率:
因为我们是逐层计算的,所以只剩下 H−1 H − 1 层的运输线没有消除影响
那么如果已经知道存在这样一条运输线,中间有多少被覆盖的旧溜索呢?
显然就是最大层数为 H−1 H − 1 ,高度为 H H 的塔的数量+1
那么我们只需要高度恰好为的楼的期望数目就可以了
注意这里的计算有一个条件:中间的
L−1
L
−
1
栋楼的高度一定不超过
H
H
下面考虑用概率公式计算
有公式(在条件成立的前提下,
A
A
发生的概率)
其中 A=楼的高度恰好为H A = 楼 的 高 度 恰 好 为 H , B=楼的高度不超过H B = 楼 的 高 度 不 超 过 H
显然
那么一栋楼高度恰好为 H H 的概率为
期望=1∗P(L−1栋楼的高度都小于H)
期
望
=
1
∗
P
(
L
−
1
栋
楼
的
高
度
都
小
于
H
)
+2∗P(一栋楼的高度为H)∗P(L−2栋楼的高度都小于H)
+
2
∗
P
(
一
栋
楼
的
高
度
为
H
)
∗
P
(
L
−
2
栋
楼
的
高
度
都
小
于
H
)
+3∗P(两栋楼的高度为H)∗P(L−3栋楼的高度都小于H)
+
3
∗
P
(
两
栋
楼
的
高
度
为
H
)
∗
P
(
L
−
3
栋
楼
的
高
度
都
小
于
H
)
+...+L∗P(L−1栋楼的高度为H)
+
.
.
.
+
L
∗
P
(
L
−
1
栋
楼
的
高
度
为
H
)
E=1∗(1−12H−1)L−1+2∗12H−1∗(1−12H−1)L−2+...+L∗(12H−1)L−1
E
=
1
∗
(
1
−
1
2
H
−
1
)
L
−
1
+
2
∗
1
2
H
−
1
∗
(
1
−
1
2
H
−
1
)
L
−
2
+
.
.
.
+
L
∗
(
1
2
H
−
1
)
L
−
1
对于每个长度
L
L
,在当前层都存在个可能位置出现溜索
那么先枚举高度,再从枚举
L
L
,综合上面的推导,我们就能得到如下的计算式:
两栋楼层编号能够达到 H H 的楼中间存在一条运输线的概率:
层数为 i i 的运输线贡献:
需要减掉的被覆盖的运输线贡献: 2i−1 2 i − 1
层数为 i−1 i − 1 (被覆盖)的运输线的期望: 1+j−12i−1 1 + j − 1 2 i − 1
这个式子用
O(nh)
O
(
n
h
)
的复杂度就可以完成
dada们表示内层可以用矩阵乘法优化然后达到
O(hlogn)
O
(
h
l
o
g
n
)
的复杂度
tip
这道题真的光速弃疗
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
char s[10];
int n,h;
double mi[200];
double KSM(double a,int b) {
double t=1.0;
while (b) {
if (b&1) t=t*a;
a=a*a;
b>>=1;
}
return t;
}
int main() {
scanf("%s",s);
scanf("%d%d",&n,&h);
if (s[0]=='B') {
printf("%d\n",n);
return 0;
}
double ans=(double)n;
mi[0]=1.0;
for (int i=1;i<=2*h;i++) mi[i]=mi[i-1]*2.0;
for (int i=1;i<=h;i++)
for (int j=1;j<=n;j++) {
double t=KSM(1.0-1.0/mi[i],j-1);
ans+=1.0*(n-j)*(1.0/mi[2*i])*t*(mi[i]-mi[i-1]*(1+(double)(j-1)/(mi[i]-1.0)));
}
printf("%.10lf\n",ans);
return 0;
}