problem
在一条公路上,有一排摩天大楼,数量在 2 ∼ 314 ! 2\sim 314! 2∼314! 之间。每一栋大楼有一个高度(正整数),高度为 i i i 的概率为 2 − i 2^{-i} 2−i。
为了出题某种特殊原因,在大楼之间安装了一些溜索,且在某栋楼的i层和另一栋楼的i层之间有一条溜索,当且仅当这两栋楼之间没有一栋大楼高度达到 i i i 层。 Alice 和 Bob 决定数一数摩天大楼的数量。
Alice 非常细心,她从最左侧的摩天大楼出发,计数器为 1 1 1。然后她向右移动,每次移到下一栋大楼,都将计数器加 1 1 1。她一直走到最右侧的大楼。(就是有多少栋数出来多少栋)。
Bob 非常没耐心,他希望尽快数完。他从最左侧的摩天大楼开始,计数器为 1 1 1。他使用溜索在大楼之间移动。每次 Bob 都用最高的溜索向右移动,但由于恐高,他会忽略掉那些编号超过 h h h 的楼层。Bob 用溜索旅行跑得比香港记者还快,以至于他根本没法数清经过了多少大楼。因此他只是将计数器加上 2 i 2^i 2i,其中 i i i 是他当前所在的楼层编号。他持续移动,直到到达最右侧的大楼。(注意编号从 0 0 0 开始)。
举个例子。有
6
6
6 栋大楼,从左到右的高度分别是
1
,
4
,
3
,
4
,
1
,
2
1,4,3,4,1,2
1,4,3,4,1,2,且
h
=
2
h=2
h=2。Alice 开始时计数器为
1
1
1,并且将计数器加了五次
1
1
1,得到的结果是
6
6
6。Bob 开始时计数器为
1
1
1,然后他依次加上
1
,
4
,
4
,
2
1,4,4,2
1,4,4,2,最终得到
12
12
12。注意,Bob 出于恐高忽略掉了最高的溜索。
当 Alice 和 Bob 到达最右端的大楼时,他们将各自的计数器拿出来比较。给出 Alice 或者 Bob 的计数器的值,你需要计算出另外一个人的计数器的期望值。
数据范围: 2 ≤ n ≤ 30000 2\le n\le30000 2≤n≤30000, 0 ≤ h ≤ 30 0\le h\le30 0≤h≤30。
solution
神仙数学题啊 orz。
推导过程看这里吧,我就只写结论了。
- Bob 推 Alice, a n s = n ans=n ans=n。
- Alice 推 Bob, a n s = n + ∑ i = 1 h ∑ j = 1 n ( n − j ) × ( 1 − 1 2 i ) j − 1 × ( 1 2 ) 2 i × ( 2 i − 2 i − 1 × ( 1 + ( j − 1 ) 1 2 i − 1 ) ) ans=n+\sum\limits_{i=1}^h\sum\limits_{j=1}^n(n-j)\times (1-\frac 1{2^i})^{j-1}\times (\frac 1 2)^{2i}\times (2^i-2^{i-1}\times (1+(j-1)\frac 1{2^i-1})) ans=n+i=1∑hj=1∑n(n−j)×(1−2i1)j−1×(21)2i×(2i−2i−1×(1+(j−1)2i−11))。
code
#include<bits/stdc++.h>
using namespace std;
char S[10];
double P[35];
double power(double a,int b){
double ans=1;
for(;b;b>>=1,a*=a) if(b&1) ans*=a;
return ans;
}
int main(){
int n,h;
scanf("%s%d%d",S,&n,&h),P[0]=1;
for(int i=1;i<=30;++i) P[i]=P[i-1]*2;
if(S[0]=='B') printf("%.9lf\n",(double)n);
else{
double ans=n;
for(int i=1;i<=n;++i)
for(int j=1;j<=h;++j)
ans+=(n-i)/P[j]/P[j]*power(1.0-1.0/P[j],i-1)*(P[j]-P[j-1]*(1.0+(i-1)/(P[j]-1)));
printf("%.9lf\n",ans);
}
return 0;
}