海爺和我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^nSn=3*2+5*4+7*8+...+(2n+1)*2^n2Sn=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/21/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²+7×3³+…+(2n-1)×3的n-1次方+(2n+1)×3的n次方……一3Tn=3×3²+5×3³+…+(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次方故得出結果。