题目链接
题目翻译
分析:
啊咧,为什么标签都是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一点用都没有(博主有毛病啊)
我们还是由浅到深
首先我们观察一下样例
啊咧,为什么输出的是一个整数不是real类型啊,好像有猫腻(不像是算出来的,倒像是读入后世界输出的)
实际上,找到AC代码试一下,发现确实是输入什么输出什么啊
不要向某人一样投机取巧,我们是可以证明:
不严谨证明:
显然,Bob每使用一次ZIP运输线,实际上经过的楼数是:在运输线下高度较小的楼+终点楼
也就是说,如果ta经过了 i i 栋楼,那么就有 i−1 i − 1 栋高度较小的楼在之间
设Bob当前计数器增加了 2H 2 H ,那么ta就在第 H H 层楼上
然而由于这个zz的编号方式,第 H H 层楼的高度实际上是 H+1 H + 1
那么ta经过的楼的高度就不会超过 H H
经过楼的期望=
1∗P(中间没有高度≤H的楼)∗P(终点楼的高度≥H) 1 ∗ P ( 中 间 没 有 高 度 ≤ H 的 楼 ) ∗ P ( 终 点 楼 的 高 度 ≥ H )
+2∗P(中间有一栋楼,高度≤H)∗P(终点楼的高度≥H) + 2 ∗ P ( 中 间 有 一 栋 楼 , 高 度 ≤ H ) ∗ P ( 终 点 楼 的 高 度 ≥ H )
+∗P(中间有两栋楼,高度≤H)∗P(终点楼的高度≥H)+... + ∗ P ( 中 间 有 两 栋 楼 , 高 度 ≤ H ) ∗ P ( 终 点 楼 的 高 度 ≥ H ) + . . .
( P P 表示概率)
题目中给出,高度为 i i 的楼出现的概率是 2−i=(12)i 2 − i = ( 1 2 ) i
因此,一栋楼的高度 ≤H ≤ H 的概率:
期望:
首先我们假设所有的楼都只有一层,编号都是0
这种情况下,Bod的计数器得到的一定是 n n
之后我们要加上一些高度更高的楼层,这样楼层之间就会出现一些ZIP运输线
此时,Bob计数器的答案就应该+运输线的贡献-覆盖掉的楼的贡献
我们一层一层的把楼加高,对于新加入的编号能达到 H H 的楼
这两栋楼的编号分别为 i,j i , j ,设 L=j−i L = j − i ,如果这两栋楼的第 H H 层之间有运输线
那么一定满足: i i 和 j j 的高度 ≥H+1 ≥ H + 1 , 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 H 的楼的期望数目就可以了
注意这里的计算有一个条件:中间的 L−1 L − 1 栋楼的高度一定不超过 H H
下面考虑用概率公式计算
有公式(在 B B 条件成立的前提下, A A 发生的概率)
期望=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 ,在当前层都存在 N−L N − L 个可能位置出现溜索
那么先枚举高度,再从枚举 L L ,综合上面的推导,我们就能得到如下的计算式:
两栋楼层编号能够达到 H H 的楼中间存在一条运输线的概率: (12i)2∗(1−12i)j−1 ( 1 2 i ) 2 ∗ ( 1 − 1 2 i ) j − 1
层数为 i i 的运输线贡献: 2i 2 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 ) 的复杂度
这道题真的光速弃疗
官方题解
#include
#include
#include
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;
}