进化论中的概率论 进化13个字母序列的无差期望值公式

进化论中的概率论 进化13个字母序列的无差期望值公式

 

原文引用=========地址:http://blog.csdn.net/pongba/archive/2007/12/02/1912466.aspx 标题:数学之美番外篇:进化论中的概率论 作者:刘未鹏(pongba)=========>

1、举个例子,现有由13个字母构成的序列“TOBEORNOTTOBE”,假设有几百万只猴子,每只猴子每秒钟挑一条短语,需要78,800年才能从26^13种可能中选出这样的排列。不过,Glendale CollegeRichard Hardison20世纪80年代写过一个程序,它能够在随机产生序列的同时,保证那些已经出现在正确位置上的字母不会变化……这个程序平均只需要336次迭代就能生成上文提到的短语,时间少于90秒。……Richard同学写的那个程序显示需要平均336次。(备注:回复中有同学指出此程序的思路是每次只写一个字母。我在想,难道意思是26*13=338336?那我就真的崩溃了。)

2、实际上,我也写了一个这样的程序,然而结果显示却是大约82次左右。那么到底谁的正确呢?(备注:作者的思路是一次写出13个字母,然后逐个对,对了就固定。)

<========引用完毕

 

首先讨论原文中解决问题的起始思路:随机写一个含有13个字母的单词,写出有且仅有一位和某个特定单词相同的单词,所用次数的期望。原文中给出了两种思路,这两种思路都是正确的,但具体计算中存在着一些问题。

方法一:猜对其中一个字母的概率是1/26,所以猜对13个字母中的一个的概率是13*(1/26)=1/2,所以期望是2

分析:假设该单词只有一个字母,猜一次猜对的概率为1/26这没有任何问题,但猜13个字母不是这样简单的叠加。26个字母猜13个数量太多不便观察,做个简单的例子:假设在五个字母ABCDE中猜出顺序为AB的一个单词,按照上面的思路,猜一次有且仅有一个正确的概率显然是2*(1/5)=2/5。现在列个表(设行为前面的字母):

 

A

B

C

D

E

A

1

 

 

 

 

B

2

1

1

1

1

C

1

 

 

 

 

D

1

 

 

 

 

E

1

 

 

 

 

显然,猜一次有且仅有一个正确的概率为8/25,猜一次对了两个的概率为1/25。和2/5完全不搭边。

 

方法二:有且仅有一个字母猜对说明其他12个均没猜对。所以猜了一次,有且仅有一个字母被猜对的概率是13*(1/26)*(25/26)^12(式①)。猜了两次才出现有一个字母被猜对情况的概率是(25/26)^n*式①,其实(25/26)^n表示的是13个字母中没有任何一个被猜对,漏掉了第一次猜的时候猜对了大于1个字母,第二次猜的时候的情况,所以从“猜了两次”的概率开始式子就开始出现偏差。正确的猜二次的概率应该是:(1-式①)*式①。

 

由于上述两思路中存在的细节错误,所以两方法得出的结果不一样纯属正常。

下面给出一个“每次有且仅有一个字母猜对”猜对整个序列所需次数的期望。在这个算法中,“每次有且仅有一个字母猜对”视为成功,“没有任何字母被猜对”以及“猜对多余1个字母”均视为失败。

13个字母的单词,有且仅有一个字母被猜对所需的猜测期望为:

1*式①+2*(1-式①)*式①+3*(1-式①)^2*式①……(式③)

=式①*n(1-式①)^(n-1)=1/式①=3.202 (计算过程见《多元函数微积分》幂级数运算性质,亦可以参阅《概率统计》中关于古典概型期望的一个定理证明,对于每次都以P概率发生的事情,让它发生一次所需的尝试次数就是1/P

然后在没有猜到的12个字母中继续猜,最后得到猜完全部13个字母需要的期望次数是94.228。该值与原文中的82差距较大,是因为这一算法考虑的是“每次有且仅有一个字母被猜对”,而非“每次有一个或以上字母被猜对”。原文中的方法二虽然在“猜一次”中采用了有且仅有一个字母被猜对的假设,但在“猜两次”~“猜N次”中又采用了“N-1”之前均为“没有猜中任何字母”的假设,漏掉了在“N-1”前可能有某些次“猜中大于1个字母”的假设,从而减少了尝试次数。

 

如原文中所述,进行字母序列猜测的时候有可能同时猜对几个字母。比如第一次有字母中标的时候一下就中了3个,那么接下来字母串的长度就变为了13-3=10

可以用这样的思路来考虑:对于序列长度为n的情况,某一次恰好猜中m个的概率为C(m,n)*(1/26)^m*(25/26)^(n-m)(式④,其中C(m,n)n个数中m个数的组合=n!/(n-m)!/m!而“恰好猜中m个”在“猜中至少1个”这一整体中发生的概率为:式④/[1-(25/26)^n](记为P(m,n))。当序列长度为13时,猜对至少一个所需次数的期望为1/(1-(25/26)^13),除了一下把13个全都猜对的情况之外,还有只猜对12个、11个……1个的情况,这些情况发生的时候则继续猜。可得猜对该序列所需次数期望E0(13)= 1/(1-(25/26)^13)+P(1,13)*E0(12)+P(2,13)*E0(11)….= 1/(1-(25/26)^13)+ P(m,13)E0(13-m)

通用公式E0(n)= 1/(1-(25/26)^n)+ P(m,n)E0(n-m)

写个程序算出来,结果为81.583。与原文中的差距是当猜到了多个字母之后序列可以缩短超过1的长度省出来的。

 

总结:I admire myself very much.

计算程序:

#include "stdio.h"

#include "math.h"

float f4(float m,float n)      /*对于序列长度为n的情况,某一次恰好猜中m个的概率为C(m,n)*(1/26)^m*(25/26)^n-m */

{

    float i;

    float t1=1,t2=1,t3=1;

    for(i=1;i<=n;i++)

    {   t1=t1*i;}

    for(i=1;i<=m;i++)

    {   t2=t2*i;}

    for(i=1;i<=n-m;i++)

    {   t3=t3*i;}

    t1=t1/t2/t3*pow((1.0/26.0),m)*pow((25.0/26.0),n-m);      /*pow(x,y),计算xy次方*/

    return(t1);

}

float P(float m,float n)                  /*"恰好猜中m""猜中至少1"这一整体中发生的概率为:f4/[1-(25/26)^n] */

{   return(f4(m,n)/(1.0-pow((25.0/26.0),n)));}

float E0(float n)

/*E0(n)=1/(1-(25/26)^n)+ P(m,n)E0(n-m)*/

{

    float m;

    float s;

    if(n==1.0)return(26.0);

    if(n==0)return(0.0);

    s=1.0/(1.-pow((25./26.),n));

    for(m=1;m<=n;m++)

    {

        s=s+P(m,n)*E0(n-m);

    }

    return(s);

}

main()

{

    float n=13;

    float t;

    t=E0(n);

    printf("%f",t);   /*想要更精确,就用double型,不过我不知道double输出的时候应该写”%”加什么啊!谁告我一下*/

    getch();

} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值