您的位置:首页 > 其它

[Codeforces335E]Counting Skyscrapers(概率期望+数学证明)

2017-03-15 14:06 246 查看

=== ===

这里放传送门

=== ===

题解

这题神死了。。。ATP想把那个在CF上强行加上【DP】这个tag的人吃掉。。。一开始吭哧了半天想了一个O(n2h)的东西根本不能做啊。。实际上这题就是一个推导,然后一个式子就出来了。。

还有,Bob这个人P事真TM多。。。。【(╯‵□′)╯︵┻━┻】

把CF的官方题解翻译先链过来。果然还是中文看起来舒爽。。。那ATP这里就把题解上没有说的证明一点一点证一下吧。。。

首先这个题看起来是强行二合一实际上并没有。。因为可以证明如果给的是Bob的计数器,那么直接把N输出来就可以了。。因为如果Bob的计数器累加了2i,那么他所经过的楼的期望数目也是2i。

这是为什么呢。。首先我们可以发现Bob每次经过一条溜索的时候,它实际上经过的楼的数量应该包括【溜索下方那些高度较小的楼】还有【作为他终点的那栋楼】。也就是说,如果他实际上经过的楼数目是i,那么它的中间有i−1栋高度较小的楼。

设当前它的计数器累加了2H,也就是说,它当前楼层的编号是H;也就是说,它当前楼层的高度是H+1(这道题恶心的地方之一就是楼层的编号和楼的高度还TM不一样= =)。那么下面那些高度较小的楼的高度必须都小于等于H。

那么我们分情况讨论,它经过的楼层数目的期望应该是1×P(中间没有小楼)P(最后一栋楼的高度大于等于H)+2×P(中间有1栋小楼)∗P(最后一栋楼的高度大于等于H)+....一直加到正无穷。而每一栋楼的高度小于等于H的概率设为P,那么我们有:

P=12+122+123+...+12H=2H−12H

然后我们就可以算Bob经过楼层数目的期望了,它是:

E=1∗P0∗(1−P)+2∗P1∗(1−P)+3∗P2∗(1−P)+...+∞∗P∞∗(1−P)

把(1−P)全都提出来以后就是等差乘等比的形式啊,话说高中数学必修五第一章学了些啥啊。。错位相减求和啊。。。

P∗E=(1∗P1+2∗P2+...+∞∗P∞)∗(1−P)E=(1∗P0+2∗P1+...+∞∗P∞)∗(1−P)

用底下的减去上面的,得到:

(1−P)E=(1∗P0+(P1+P2+..+P∞))(1−P)

两边能够约掉一个1−P辣!接着看中间那一坨等比数列,首先等比数列的求和公式是a1(1−qn)1−q,这里的q是满足0<q<1的,那么当n→∞的时候,qn→0,然后这个东西就变成了a11−q。有了这个结论就可以把上面的式子化成:

E=1+P1−P=11−P

话说P是啥来着?把P=2H−12H往里面一代就是E=2H辣!

Bob只是小杂鱼。。真正的Boss其实是Alice qwq。。。

搞定Alice的基本思路是先假设所有的楼都只有1层,也就是它们的编号都是0;那这样的话Bob的计数器肯定只能是N;然后再考虑加上一些高度更高的楼层,那么这种变化势必会加上一些溜索,那么Bob的计数器就要先【加上新溜索带来的贡献】再【减去被覆盖掉的旧溜索的贡献】。

我们一层一层把楼加高,对于新加入的编号能够达到H的塔,考虑它们中间存在一条溜索的可能性。如果这两座塔的坐标分别是i和j(i<j),定义它们之间的距离L=j−i,那么如果这两座塔的编号为H的层之间存在溜索,首先这两座塔的高度必须不小于H+1,并且它们中间所有的L−1座塔高度必须严格小于H+1。

这两个显然是补集关系,算了一个就能算另一个。那么我们就算中间每一座塔的高度小于H+1的概率好了。设这个概率为P(众:怎么又是P你不觉得你字母重复了么。。ATP:你管我呢= =),那么有:

P=P=12+122+123+...+12H=2H−12H

(和上面是一样的嘿嘿嘿)

那么两边的塔的高度都不小于H+1的概率就是1−P=12H。然后就可以知道,两座编号能够达到H的塔中间存在一条溜索的可能性就是:P2PL−1=122H∗(1−12H)L−1

那么如果已经知道存在这样一条连接两个编号为H的楼层的溜索,它们中间有多少被覆盖的旧溜索呢?显然就是最大编号为H−1的塔的数量+1。那么我们只需要计算下面最大编号为H−1,也就是高度恰好为H的塔的数目的期望就可以了。

注意这里的计算有一个条件就是已经确定了中间这L−1个塔的高度都不大于H,那么这里应该用条件概率的规则来计算。根据公式P(A|B)=P(A⋂B)P(B),对于每一座塔来说,事件B——它的高度不大于H的概率就是P=2H−12H,而事件A——它的高度恰好为H的概率是12H。而显然这里A和B是互相独立的,P(A⋂B)=P(A)。那么这L-1座塔中的每一座塔的高度恰好为H的概率都是:

P(A⋂B)P(B)=12H×2H2H−1=12H−1

于是我们可以得到中间被覆盖的旧溜索数目的期望:

1+L−12H−1

而由于塔的高度的随机性,这里的L显然可以是任意的。那么对于每个长度L,在当前层都存在N−L个可能位置出现溜索。那么先从1开始枚举高度,再从1开始枚举L,综合上面的推导,我们就能得到如下的计算式:

N+∑i=1H∑j=1N(N−j)∗122i∗(1−12i)j−1∗(2i−2i−1∗(1+j−12i−1))

至此终于把Alice搞定辣!这个式子用O(nh)的复杂度就可以很愉悦地搞出来!据说内层可以用矩阵乘法优化然后达到O(hlogn)的复杂度?好在出题人的良心还剩下了那么一点点

代码

话说那一坨式子写出来好恶心啊

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char w[10];
int N,H;
double ans,bin[60010];
double powww(double a,int t){
double ans=1;
while (t!=0){
if (t&1) ans=ans*a;
a=a*a;t>>=1;
}
return ans;
}
int main()
{
scanf("%s",w);
scanf("%d%d",&N,&H);
if (w[0]=='B'){
printf("%.10lf\n",(double)N);
return 0;
}
ans=N;bin[0]=1;
for (int i=1;i<=2*H;i++)
bin[i]=bin[i-1]*0.5;
for (int i=1;i<=H;i++)
for (int j=1;j<=N;j++){
double tmp=N-j;
tmp=tmp*bin[2*i]*powww(1-bin[i],j-1)*(1/bin[i]-1/bin[i-1]*(1+(double)(j-1)/(1/bin[i]-1)));
ans+=tmp;
}
printf("%.10lf\n",ans);
return 0;
}


偏偏在最后出现的补充说明

化式子这东西好神奇啊

把它化得它妈妈都不认识它了然后竟然能算出正确的结果来哈哈哈哈
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息