1.扔三顆骰子,求點數之和最大值出現的概率?
思想:三顆骰子的和數取值範圍在[3,18],越靠近兩邊出現的概率越小,點數最大的應該在中間,以下計算9,10,11,12的概率:
* * 首先計算出現9的概率:爲了避免重複和遺漏,將點數和爲9分成兩種情況:
(1)三個骰子點數都不相同:(1,2,6),(1,3,5),(2,3,4)
(2)可以允許存在相同的點數:(2,2,5),(3,3,3),(4,4,1)。
全不相同時對三個點數全排列,因此(1,2,6)排列共有3!= 6 種情況,存在相同點數時將不同的那個元素提出來利用插空法,所以(2,2,5)排列有3種,總的概率
P = (3! * 3 + 3* 2 + 1)/6*6*6 = 25/216.
* * 點數和爲10時,可以分爲:(1)(1,3,6),(1,4,5),(2,3,5);(2)(2,2,6),(3,3,4),(4,4,2)。
P = (3! * 3 + 3 * 3)/6*6*6 = 27/216
* * 點數和爲11時,也分爲兩種情況:(1)(1,4,6),(2,3,6),(2,4,5); (2)(3,3,5),(4,4,3),(5,5,1)
P = (3! * 3 + 3 * 3)/6*6*6 = 27/216
* * 點數和爲12,(1)(1,5,6),(2,4,6),(3,4,5); (2)(3,3,6),(4,4,4),(5,5,2)
P = 25/216
所以點數和最大的可能是10或者11.
2. 網易遊戲的骰子游戲
題目描述:
小易參加了一個骰子游戲,這個遊戲需要同時投擲n個骰子,每個骰子都是一個印有數字1~6的均勻正方體。
小易同時投擲出這n個骰子,如果這n個骰子向上面的數字之和大於等於x,小易就會獲得遊戲獎勵。
小易想讓你幫他算算他獲得獎勵的概率有多大。
輸入描述:
輸入包括兩個正整數n和x(1 ≤ n < 25, 1 ≤ x < 150),分別表示骰子的個數和可以獲得獎勵的最小數字和。
輸出描述:
輸出小易可以獲得獎勵的概率。
如果概率爲1,輸出1,如果概率爲0,輸出0,其他以最簡分數(x/y)的形式輸出。
解題思路:
可能出現的值的範圍爲:n~6*n
1、回溯法
回溯法枚舉n個骰子(6面)的全排列,然後計算每一次排列所有值的和,並統計該和的出現的次數,除以6^n(全排列的全部可能性),即爲概率。
2. DP 動態規劃
假設f(m,s)表示投第m個骰子時,點數之和s出現的次數,投第m個骰子時的點數之和只與投第m-1個骰子時有關。
遞歸方程:f(m,s)=f(m-1,s-1)+f(m-1,s-2)+f(m-1,s-3)+f(m-1,s-4)+f(m-1,s-5)+f(m-1,s-6),表示本輪點數和爲s出現次數等於上一輪點數和爲s-1,s-2,s-3,s-4,s-5,s-6出現的次數之和。
初始條件:第一輪的f(1),f(2),f(3),f(4),f(5),f(6)均等於1.
需要求的是:f(n , n)、 f(n, n+1)....f(n, 6*n)
下面的代碼: 是用了空間壓縮的dp,並且一定要注意 dp數組應該是long long,因爲全部排列的6^n 很大,用int會溢
def probility(n, x):
dp = [[0]*6*n+[0] for _ in range(n)]
for i in range(1,7):
dp[0][i] = 1
for i in range(1,n):
for j in range(1,(i+1)*6+1):
for k in range(1,min(7, j+1)):
dp[i][j] += dp[i-1][j-k]
res = 0
for i in range(x,n*6+1):
res += dp[-1][i]
return res
def gcd(a, b):
while b:
a, b = b, a%b
return a
n, x = map(int, input().split())
if x <= n:
print(1)
elif x > n*6:
print(0)
else:
pro = probility(n, x)
cum = 6**n
g = gcd(pro, cum)
print(str(pro//g)+'/'+str(cum//g))