一副撲克牌,隨機洗牌後,至少有一組相鄰兩張牌數字相同的概率是多少?

每次在洗撲克牌時,我就會想這個問題. 困擾我很長時間. 因為每次洗牌後,我發現總有至少有兩張數字相同的牌相鄰,所以我認為這是個高概率事件.不知道哪位高手能夠算出確切的概率,感激不盡.

相關問題:一副撲克牌(去掉大小王)。隨機選1~K中的兩個數字,洗牌後將牌扇形攤開,所選兩數的牌相鄰概率? - 概率論


謝邀。

這個問題算確切值是有點困難的,不過有個不錯的方法迅速估算一下,大概只需幾秒鐘。

估算的結果大約是 1-e^{-3} approx  95.2 %

本題計算結果的補集會比較方便,即:一副撲克牌隨機洗牌後,相鄰牌的數字都不同的概率。

顯而易見,在確定第 1 張牌後,第 2 張牌和其相同的概率是 3/51。

類似地,第 2 張和第 3 張、第 3 張和第 4 張、……、第 51 張和第 52 張相同的概率也是 3/51。

以下是第一個近似:把上面 51 個事件看作獨立事件

顯然,這 51 個事件是相關的,之所以把其看作獨立事件,是因為每一件事情發生的概率都相對較小(雖然 1/17 也是一個不小的數了),因此兩件事情同時發生的概率近似可以看作二階小量。

於是我們要求的補集是 left( 1-3/51 
ight)^{51}

如果學過一點點微積分,應該知道這個公式:

lim_{x 
ightarrow infty }{(1-1/x)^{x}}=1/e

於是我們用到了第二個近似:把 51 看作一個很大的數;

left( 1-3/51 
ight)^{51} approx e^{-3}

所以本題估算的結果大約是 1-e^{-3} approx  95.2 %

註:上面一個算式也可以直接求結果:1-left( 1-3/51 
ight)^{51} approx 0.95458

這和 @莫濤 算出的精確值只有十萬分之六的差別

#

(之前的答案有誤,已刪除)


在去掉大小鬼的情況下,52張牌中至少有一組相鄰兩張牌數字相同的概率是0.9545237176689056。相應的,任意相鄰兩張牌數字都不同的可能性一共有3668033946384704437729512814619767610579526911188666362431432294400種。

方法:狀態壓縮動態規劃,使用記憶化搜索實現

狀態表示:f(n0, n1, n2, n3, n4, last)為剩餘0張的數字有n0種,剩餘1張的數字有n1種...剩餘4張的數字有n4種,上一張牌現在還剩last張

狀態轉移:枚舉下一張牌屬於哪一類,注意和上一張牌不同即可

答案:f(0, 0, 0, 0, 13, 0)

代碼:scala/poker.scala at master · mythly/scala · GitHub


謝邀

幾位高票答主已經闡述了【求補集】這個思路的好,我來給題主大概算一下【正著求】的難處。

Step1. 首先,我們先解決一個簡單的數學問題:

任意一副隨機洗牌的撲克中(不含大小鬼),一個紅桃A和一個黑桃A相鄰的概率。

這個問題簡單吧,剩餘50張牌隨機洗牌共有50!種情況,他們共產生51個空位,兩個A挨著並插入這些空位:

P = 2*51*50!/52! = 1/26。

Step2.我們計算一下【A?】【A?】【A?】三個A中任意兩個A相鄰的概率

如果你脫口而出3*1/26,恭喜你,你已經可以不用往下看了。

為什麼不是3/26?因為,你會重複數一些情況,而這些情況就是,3個A都相鄰的。他們共有

3!*50*49!/52!種,所以

P = 3*1/26 - 3!*50*49!/52! = 75/663

為什麼重複數了3個A都相鄰的,並重複數了一次呢?為了後續論述的方便,讓我們給一個簡單的證明。

我們來考慮3張牌都挨著的6種情況。拿任意一種情況說明,比如,【A?】【A?】【A?】這個順序的情況下,在計算【A?】【A?】和【A?】【A?】時,我們都數了這個情況,所以重複數了一次。

Step3.進一步,我們來計算一下

【A?】【A?】【A?】【A?】中任意兩個A相鄰的概率,即,一副隨機洗好的撲克牌中,有兩個A相鄰的概率

答案當然不是6*1/26了!能給出這個答案的同學已經在Step2被篩選掉了。

那麼,對於4張A有兩個相鄰的情況,我們重複數了哪些呢?首先,我們重複數了所有3張A相鄰的情況,他們是4*3*2*50*49!種。而後,我們重複數了4張A相鄰的情況,他們是4!*49*48!種。所以,減去這些情況的結果 6*1/26 - 4*3*2*50*49!/52! - 4!*49*48!/52! 對么?如果你覺得是對的,可以停止往下看了。

看到這裡的聰明的你可能已經發現了3個問題:a、3張牌挨著包含了4張牌挨著;b、4張牌挨著的並不是被重複數了一次,故而減去一次可能不合理;c、即使不是3張牌挨著或4張牌挨著,也有情況被重複數了:4張A兩兩挨著。那麼,為了解決這個問題,我們來看看這些重複的項究竟該被減去幾次?

首先,3張牌挨著,如Step2,他被重複數了一次,故而應該減去一次;4張牌挨著,在6*1/26這個項里,被重複數了3次,在4*3*2*50*49!/52!里被重複數了2次,故而,4張牌挨著已經不用加減了;4張A兩兩挨著,為了避免4張牌挨著被重複計算,我們規定,這個情況只限於4張A兩兩挨著,但他們互相不挨著,這樣的情況共有48!*C(49,2)*4!種(解釋一下,剩餘48張牌洗好,產生49個空位,在49個空位中選2個空位,分別放入兩張AA)。綜上,

P = 6*1/26 - 4*3*2*50*49!/52! - 48!*C(49,2)*4!/52! = 1201/5525

怎麼知道我們這個數字是對是錯呢?

我們用【求補集】的方法檢驗一下。

P = 1 - 48! * A(49,4) / 52! = 1201/5525

Step4. 已知,一副隨機洗好的撲克牌中,兩張A挨著的概率是1201/5525,兩張K挨著的概率是1201/5525。求:一副隨機洗好的撲克牌中,兩張A或兩張K挨著的概率

這個問題我已經難以回答了,因為在2*1201/5525的情況下,被重複計算的情況太多了:AAKK、AAKKAA、AAKKAAKK、AAAKKK等等等等,數不勝數。

要計算這個(【正著算】)已經很難了,如果要正著算任意兩張數字相同的牌挨著的概率,可謂難上加難。

Step5.已知,一副隨機洗好的撲克牌中,兩張A挨著的概率是1201/5525,兩張K挨著的概率是1201/5525,兩張Q挨著的概率是1201/5525…………兩張2挨著的概率是1201/5525,求:一副隨機洗好的撲克牌中,兩張數字相同的牌挨著的概率。

就是這道問題了。

還好,我們有:

容斥原理(容斥原理_百度百科):

我們把前面解題的步驟套入容斥原理。先來看,一副牌中,有兩張A相鄰的概率。

一共有6個集合,分別是{A?和A?相鄰}、{A?和A?相鄰}…………{A?和A?相鄰}(記為A1 - A6)。根據容斥原理,要求{A1cup A2cup A3cup A4cup A5cup A6}集合的大小。那麼,它應該等於sum_{i=1}^{6}{left| Ai 
ight| } - sum_{i
e j}^{}{left| Aicap Aj 
ight| } + sum_{i,j,k}^{}{left| Aicap Ajcap Ak 
ight| } - 0 + 0 - 0,注意,後3個0值分別表示任4個、任5個、6個集合的交集,由於這些集合是空集,所以,他們的元素個數為0。這個式子大家整理後,就是我前面的(稍有差別,我把sum_{i,j,k}^{}{left| Aicap Ajcap Ak 
ight| }這一項合併到了前面):

P = 6*1/26 - 4*3*2*50*49!/52! - 48!*C(49,2)*4!/52! = 1201/5525

現在,我們看看容斥原理能不能幫助我們解決題主的問題。

首先,我們定義6*13=78個集合:{A?和A?相鄰}、{A?和A?相鄰}…………{A?和A?相鄰}、{K?和K?相鄰}、{K?和K?相鄰}…………{K?和K?相鄰}…………{2?和2?相鄰}、{2?和2?相鄰}…………{2?和2?相鄰}。並將他們稱為A1-A78。我們還是要求left| A1cup A2 ... cup A78 
ight| ,根據容斥原理,它應該等於

sum_{i=1}^{78}{left| Ai 
ight| } - sum_{i
e j}^{}{left| Aicap Aj 
ight| } + sum_{i,j,k}^{}{left| Aicap Ajcap Ak 
ight| } - ... + ...,如果我們願意省略後面的項(他們的數值大都足夠小),看看計算前3項是否能給出一個近似的結果。

第一項,78*1/26

第二項,兩種情況,一是Ai和Aj的集合里,有一張牌一模一樣,這時,這一項表徵了3張牌相連的個數。概率為13*4*3*2*50*49!/52!;第二種情況,Ai集合中的牌和Aj集合中的牌沒有重複的,概率為:C(78,2)*50!*2*2/52!

第三項,很複雜,我們暫時忽略。

所以,P=78/26-13*4*3*2*50!/52!-C(78,2)*50!*2*2/52! = -81/51(看來忽略第三項不行啊)

思路就是這樣,我回頭有空的時候討論一下第三項吧。

硬廣:隨機 - 知乎專欄


蒙特卡羅方法:

import random

all_cards=range(1,14)
all_cards.extend(all_cards)
all_cards.extend(all_cards)
print all_cards

total=1000000
hit=0

for count in range(0,total):
random.shuffle(all_cards)
for card_index in range(0,len(all_cards)-1):
if(all_cards[card_index] == all_cards[card_index+1]):
hit = hit + 1
break

print "%2.2f%%"%(100.0*hit/total)

大約 95%~96%


答案有誤,已經刪除!


講一下我的想法,採用遞推的方法。

首先,我們要計算至少有兩張相鄰的牌數字相同,可以從反方面來考慮,計算任何沒有兩張相鄰的牌數字相同。

下面引入幾個符號:

p_{0}(n) :1—n數字的牌(每個數字有四張),共4n張,進行排序, 沒有相鄰的兩張牌數字相同,所有排列的個數。

p_{1}(n) :1—n數字的牌(每個數字有四張),共4n張,進行排序,恰有一對相鄰兩張牌數字相同,所有排列的個數。

p_{2}(n) :1—n數字的牌(每個數字有四張),共4n張,進行排序,恰有兩對相鄰兩張牌數字相同,所有排列的個數。

p_{3}(n) :1—n數字的牌(每個數字有四張),共4n張,進行排序,恰有三對相鄰兩張牌數字相同,所有排列的個數。

p_{4}(n):1—n數字的牌(每個數字有四張),共4n張,進行排序,恰有三對相鄰兩張牌數字相同,所有排列的個數。

假設將相同數字,不同花色的牌看成是一模一樣的。

那麼最終我們要求的概率是1- left[ p_{0}(13) 
ight] /left[ 52!/(4!)^{13}  
ight] 。 下面來求p_{0}(13)

遞推關係:p_{0}(n)=p_{0}(n-1)ullet C_{4(n-1)+1}^{4}
+p_{1}(n-1)ullet C_{4(n-1)+1-1}^{3}
+p_{2}(n-1)ullet C_{4(n-1)+1-2}^{2}
+p_{3}(n-1)ullet C_{4(n-1)+1-3}^{1}
+p_{4}(n-1)ullet C_{4(n-1)+1-3}^{0}

解釋:第一項的意思是前4(n-1)張牌已經排好,共有4(n-1)+1個空位可以讓接下來的4張數值為n的牌插入。公式中的第二項也類似,不同的是原來4(n-1)張牌在排序時有相鄰兩張牌是數字相同的,為了達到最後沒有相鄰牌數字相同的問題,必須有一張數值為n的牌插在這裡,因此之後只能是剩下的3張牌插在4(n-1)+1-1個空位中,即C_{4(n-1)+1-1}^{3} 。上述公式中的其他幾項也是類似道理,不在贅述。

同樣的方法也可以求出p_{1}(n) ,  p_{2}(n) ,  p_{3}(n) ,  p_{4}(n) , 的遞推關係。

初值條件:p_{0}(1)= p_{1}(1)= p_{2}(1)= p_{4}(1)= 0p_{3}(1)=1

根據這樣的遞推關係就能求出p_{0} (13)

最終求出1- left[ p_{0}(13) 
ight] /left[ 52!/(4!)^{13}  
ight]

計算比較複雜,請大神幫忙算算。。。。


推薦閱讀:

如何做好「推薦演算法」?有哪些常見的錯誤需要避免?
請問隨機森林為什麼不會過度擬合?
有沒有機器學習方面集大成的教材推薦?
枚舉和窮儘是不是最有效,最暴力的演算法?
哪本《數據結構與演算法》最好?

TAG:演算法 | 撲克 | 概率 |