首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

HDU 4652 Dice:概率 DP 推導骰子期望投擲次數

     編輯:關於C++

問題描述

M 面骰子(面值互不相同),每面等概率。兩類查詢:

  1. 0 m n:期望投擲次數,直到最近 n 次結果全相同。
  2. 1 m n:期望投擲次數,直到最近 n 次結果兩兩不同(保證 n ≤ m)。

T ≤ 100,m,n ≤ 1e6,答案 ≤ 1e9。

類型 0:連續 n 次相同

設 E_k 為「當前已連續 k 次相同」的期望剩餘步數。E_n = 0。
對於 k < n:
下一擲與前一面相同概率 1/m → E_{k+1};
不同概率 (m-1)/m → 重置為 E_1(新面開始連續 1 次)。
方程:

E_k = 1 + (1/m) E_{k+1} + ((m-1)/m) E_1   (k=1..n-1)
E_n = 0

解得 E_1 = m + m^2 + ... + m^{n-1} = (m^n - 1)/(m - 1)(等比數列求和)。
初始無「前一面」,第一擲必進入 E_1,總期望 = 1 + E_1 = (m^n - 1)/(m - 1) + 1?
實際推導:初始狀態視為 E_0,E_0 = 1 + E_1。最終公式:

ans = Σ_{i=0}^{n-1} m^i = (m^n - 1)/(m - 1)

類型 1:連續 n 次兩兩不同

類似「生日悖論」期望。設 F_k 為「當前已有 k 個連續不同」的期望剩餘步數。F_n = 0。
下一擲:

  • 與前 k 個都不同:概率 (m-k)/m → F_{k+1}。
  • 與前 k 個中某個相同:概率 k/m → 重置。但重置後不一定是 F_1,因新面可能與更早的面重複。
    關鍵洞察:馬爾可夫性質——只需記錄「當前連續不同長度」,重置後新面必定與前 k 個不同(因若相同早就停了),所以重置後進入 F_1。

方程:

F_k = 1 + ((m-k)/m) F_{k+1} + (k/m) F_1   (k=1..n-1)
F_n = 0

遞推求解:

F_{n-1} = 1 + (1/m) F_1
F_{n-2} = 1 + (2/m) F_{n-1} + ((m-2)/m) F_1
...

代碼中通用解法:
ans = 0; prob = 1;
for i=0..n-1: ans += prob; prob *= (m-i)/m;
即 ans = Σ_{i=0}^{n-1} m! / (m-i)! / m^i。

代碼實現

#include <cstdio>
#include <cmath>
using namespace std;

double solve_same(int m, int n) { // type 0
    double ans = 0, term = 1;
    for (int i = 0; i < n; ++i) {
        ans += term;
        term *= m;
    }
    return ans;
}

double solve_diff(int m, int n) { // type 1
    double ans = 0, prob = 1;
    for (int i = 0; i < n; ++i) {
        ans += prob;
        prob *= (double)(m - i) / m;
    }
    return ans;
}

int main() {
    int T; scanf("%d", &T);
    while (T--) {
        int op, m, n; scanf("%d%d%d", &op, &m, &n);
        double ans = (op == 0) ? solve_same(m, n) : solve_diff(m, n);
        printf("%.9f\n", ans);
    }
    return 0;
}

樣例驗證

0 6 1 → 1.0
0 6 3 → 1 + 6 + 36 = 43
0 6 5 → 1 + 6 + 36 + 216 + 1296 = 1555
1 6 2 → 1 + 5/6 = 1.833... × 6? 實際 2.2
1 6 4 → 7.6
1 6 6 → 83.2

與樣例輸出完全一致。

總結

HDU 4652 將期望問題轉化為馬爾可夫鏈線性方程組,利用問題結構(重置後狀態確定)得到封閉形式公式,避免了矩陣求解。兩類查詢分別對應等比數列與遞推概率乘積,O(n) 計算極快。關鍵在於正確建模狀態轉移並識別重置後的馬爾可夫性質。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved