关于骰子的一道算法题(期望、求和、错位相减)

来源:互联网 发布:多媒体显示屏播放软件 编辑:程序博客网 时间:2024/05/18 01:32

海爷和我share了一个很有意思的算法题:


FROM:http://ilewen.com/questions/1534

一个骰子,6面,1个面是 1, 2个面是2, 3个面是3, 问平均掷多少次能使1,2,3都至少出现一次!


首先要知道这个题求什么,最先直接没理解

这题可以翻译为,一个骰子,6面,1个面是 1, 2个面是2, 3个面是3,随机扔骰子,在第x次时3个数都出现,求这个x的期望(也就是扔无数次,x的平均值是多少)

思路:

第一二次肯定不可能出现这种情况

第x(x > 2)次三个都出现的情况分三种(x ^ y 表示 x 的 y 次方)

1:第x次出现 1,那么前面出现的必然是 2 和 3 ,且至少出现一次

出现1的概率为 1 / 6,前面x-1次不出现1的概率为(1 - 1 / 6) ^ (x - 1),

但是其中包含全是 2 和全是 3 的情况,去掉全 2 的概率 (1 / 2) ^ (x - 1),全部为3的概率(1 / 3) ^ (x - 1),

那么情况 1 的概率为 ((1 - 1 / 6) ^ (x - 1) - (1 / 2) ^ (x - 1) - (1 / 3) ^ (x - 1)) * (1 / 6)

2:第x次出现2,那么前面出现的必然是 1 和 3 ,且至少出现一次 同样,概率为 ((1 - 1 / 3) ^ (x - 1) - (1 / 2) ^ (x - 1) - (1 / 6) ^ (x - 1)) * (1 / 3)

3:第x次出现3,那么前面出现的必然是 1 和 2 ,且至少出现一次 同样,概率为 ((1 - 1 / 2) ^ (x - 1) - (1 / 3) ^ (x - 1) - (1 / 6) ^ (x - 1)) * (1 / 2)

p(x)就为上面三种情况的和

那么,根据期望公式,平均值就等于从x = 3 到 n(无穷)求(x * p(x))的和

利用错位相减法计算极限值,附代码

#include "stdio.h" #include "math.h"const int MAX_TRY = 10000;double funBase(double x){    return x * x * (3 + x / (1 - x));}double funOne(double x)//每种情况的极限{    x = 1 - x;    return funBase(x) - funBase(1 - x);}double funThree(double x1, double x2, double x3){    return funOne(x1) + funOne(x2) + funOne(x3);//三种情况的极限和}double funTimeBase(double x, int n){    return x * pow((1 - x), n) - (1 - x) * pow(x, n);}double funTimeOne(double x1, double x2, double x3, int n){    return funTimeBase(x1, n) + funTimeBase(x2, n) + funTimeBase(x3, n);}double funTimeAll(double x1, double x2, double x3, int start, int n){//简单的变化    double total = 0;    for (int i = start; i < n; ++i)    {        double look = funTimeOne(x1, x2, x3, i);        total += (i + 1)* look;    }    return total;}double funDirectOne(double x1, double x2, double x3, int n){    double ret = 0;    ret += x1 * (pow((1 - x1), n) - pow(x2, n) - pow(x3, n));    ret += x2 * (pow((1 - x2), n) - pow(x1, n) - pow(x3, n));    ret += x3 * (pow((1 - x3), n) - pow(x2, n) - pow(x1, n));    return ret;}double funDirectAll(double x1, double x2, double x3, int start, int n){//按各种情况直接求和    double total = 0;    for (int i = start; i < n; ++i)    {        double look = funDirectOne(x1, x2, x3, i);        total += (i + 1) * look;    }    return total;}int main() {        //后面的start = 2表示第三次的概率    double ret = funTimeAll(1.0 / 6, 1.0 / 2, 1.0 / 3, 2, MAX_TRY);    printf("%f ", ret);    ret = funThree(1.0 / 6, 1.0 / 2, 1.0 / 3);    printf("%f ", ret);    ret = funDirectAll(1.0 / 6, 1.0 / 2, 1.0 / 3, 2, MAX_TRY);    printf("%f\n",ret);    return 0;}



先把我的运行结果发出来:




错位相减法是一种常用的数列求和方法,应用于等比数列等差数列相乘的形式。 形如An=BnCn,其中Bn为等差数列,Cn为等比数列;分别列出Sn,再把所有式子同时乘以等比数列的公比,即kSn;然后错一位,两式相减即可。

如果数列的各项是由一个等差数列和一个等比数列的对应项之积构成的,那么这个数列的前n项和可用此法来求,如等比数列的前n项和公式就是用此法推导的

例如:求和Sn=1+3x+5x^2+7x^3+…+(2n-1)*x^(n-1)(x≠0)
当x=1时,Sn=1+3+5+…+(2n-1)=n^2;
当x不等于1时,Sn=1+3x+5x^2+7x^3+…+(2n-1)*x^(n-1);
∴xSn=x+3x^2+5x^3+7x^4+…+(2n-1)*x^n;
两式相减得(1-x)Sn=1+2[x+x^2+x^3+x^4+…+x^(n-1)]-(2n-1)*x^n;
化简得Sn=1/1-x+(2x-2x^n)/(1-x)^2-(2n-1)*x^n/1-x

错位相减法是求和的一种解题方法。在题目的类型中:一般是a前面的系数和a的指数是相等的情况下才可以用。
这是例子:
S=a+2a^2+3a^3+……+(n-2)a^(n-2)+(n-1)a^(n-1)+na^n (1)
在(1)的左右两边同时乘上a。 得到等式(2)如下:
aS= a^2+2a^3+3a^4+……+(n-2)a^(n-1)+(n-1)a^n+na^(n+1) (2)
用(1)—(2),得到等式(3)如下:
(1-a)S=a+(2-1)a^2+(3-2)a^3+……+(n-n+1)a^n-na^(n+1) (3)
(1-a)S=a+a^2+a^3+……+a^(n-1)+a^n-na^(n+1)
S=a+a^2+a^3+……+a^(n-1)+a^n用这个的求和公式。
(1-a)S=a+a^2+a^3+……+a^(n-1)+a^n-na^(n+1)
最后在等式两边同时除以(1-a),就可以得到S的通用公式了。
例子:求和Sn=3x+5x^2+7x^3+……..+(2n-1)·x的n-1次方(x不等于0)
解:当x=1时,Sn=1+3+5+…..+(2n-1)=n^2;;
当x不等于1时,Sn=3x+5x^2+7x^3+……..+(2n-1)·x的n-1次方
所以xSn=x+3x^2+5x^3+7x四次方……..+(2n-1)·x的n次方
所以两式相减的(1-x)Sn=1+2x(1+x+x^2+x^3+...+x的n-2次方)-(2n-1)·x的n次方。
化简得:Sn=(2n-1)·x地n+1次方-(2n+1)·x的n次方+(1+x)/(1-x)平方
Cn=(2n+1)*2^n
Sn=3*2+5*4+7*8+...+(2n+1)*2^n
2Sn=3*4+5*8+7*16+...+(2n-1)*2^n+(2n+1)*2^(n+1)
两式相减得
-Sn=6+2*4+2*8+2*16+...+2*2^n-(2n+1)*2^(n+1)
=6+2*(4+8+16+...+2^n)-(2n+1)*2^(n+1)
=6+2^(n+2)-8-(2n+1)*2^(n+1) (等比数列求和)
=(1-2n)*2^(n+1)-2
所以Sn=(2n-1)*2^(n+1)+2
错位相减法
这个在求等比数列求和公式时就用了
Sn= 1/2+1/4+1/8+....+1/2^n
两边同时乘以1/2
1/2Sn= 1/4+1/8+....+1/2^n+1/2^(n+1)(注意跟原式的位置的不同,这样写看的更清楚些)
两式相减
1/2Sn=1/2-1/2^(n+1)
Sn=1-1/2^n
例题1
已知等比数列an中,a1=3,点(an,an+1(角码,
后不解释))在直线y=x+2上
①求数列an的通项公式
②若bn=an×3的n次方,求数列前n项和Tn
解:①点(an,an+1)在直线y=x+2上,an+1=an+2(2为常数)
即an+1-an=2.所以an是以3为首项,2为公差的等差数列
②bn=an×3的n次方,bn=(2n+1)×3的n次方
Tn=3×3+5×3&sup2;+7×3&sup3;+…+(2n-1)×3的n-1次方+(2n+1)×3的n次方……一
3Tn=3×3&sup2;+5×3&sup3;+…+(2n-1)×3的n次方+(2n+1)×3的n+1次方……二
一减二得 9+2×(9(1-3的n-1次方)\1-3)-(2n+1)×3的n+1次方=-2n×3的n+1次方
所以Tn=n×3的n+1次方
故得出结果。