【HDOJ】4652 Dice

时间:2023-03-08 18:37:25
【HDOJ】4652 Dice

1. 题目描述
对于m面的骰子。有两种查询,查询0表示求最后n次摇骰子点数相同的期望;查询1表示最后n次摇骰子点数均不相同的期望。

2. 基本思路
由期望DP推导,求得最终表达式。
(1) 查询0
    不妨设$dp[k]$表示当前已经有k次相同而最终实现n次相同的期望。
    \begin{align}
        dp[0] &= 1 + dp[1]  \notag \\
        dp[1] &= 1 + \frac{1}{m}dp[2] + \frac{m-1}{m}dp[1]  \notag \\
        dp[2] &= 1 + \frac{1}{m}dp[3] + \frac{m-1}{m}dp[1]  \notag  \\
              &\cdots       \notag \\
        dp[n-1] &= 1 + \frac{1}{m}dp[n] + \frac{m-1}{m}dp[1] \notag \\
        dp[n] &= 0
    \end{align}
    两两相减可得。
    \begin{align}
        dp[0]-dp[1] &= \frac{1}{m}(dp[1]-dp[2]) \notag \\
        dp[1]-dp[2] &= \frac{1}{m}(dp[2]-dp[3]) \notag \\
        dp[2]-dp[3] &= \frac{1}{m}(dp[3]-dp[4]) \notag \\
                    &\cdots \notag \\
        dp[n-2]-dp[n-1] &= \frac{1}{m}(dp[n-1]-dp[n])
    \end{align}
    由$dp[0]=1+dp[1], dp[0]-dp[1]=1$代入可得。
    \begin{align}
        dp[0]-dp[1] &= 1 \notag \\
        dp[1]-dp[2] &= m \notag \\
        dp[2]-dp[3] &= m^2 \notag \\
                    &\cdots \notag \\
        dp[n-1]-dp[n] &= m^{n-1}
    \end{align}
    显然是一个等比数列,累加后可得$dp[0]-dp[n]=dp[0]$.
    \begin{align}   
        dp[0] = \frac{m^n-1}{m-1}
    \end{align}

(2)查询1
    不妨设$dp[k]$表示当前已经有k个不同而最终实现n个不同的期望。
    \begin{align}
        dp[0] &= 1 + dp[1] \notag \\
        dp[1] &= 1 + \frac{1}{m}dp[1] + \frac{m-1}{m}dp[2] \notag \\
        dp[2] &= 1 + \frac{1}{m}dp[1] + \frac{1}{m}dp[2] + \frac{m-2}{m}dp[3] \notag \\
                &\cdots \notag \\
        dp[n-1] &= 1 + \Sigma_{i=1}^{n-1}{\frac{1}{m}dp[i]} + \frac{m-(n-1)}{m}dp[n] \notag \\
        dp[n] &= 0
    \end{align}
     两两相减可得。
    \begin{align}
        dp[0]-dp[1] &= \frac{m-1}{m}(dp[1]-dp[2]) \notag \\
        dp[1]-dp[2] &= \frac{m-2}{m}(dp[2]-dp[3]) \notag \\
                    &\cdots \notag \\
        dp[n-2]-dp[n-1] &= \frac{m-(n-1)}{m}(dp[n-1]-dp[n])
    \end{align}
    由$dp[0]=1+dp[1], dp[0]-dp[1]=1$代入累加后可得。
    \begin{align}
        dp[0] = \Sigma_{i=1}^{n} \frac{m^i}{\prod_{j=0}^{i-1}(m-j)}
    \end{align}

3. 代码

 /* 4652 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 #define LL __int64 int t;
int op, n, m; LL Pow(LL base, int n) {
LL ret = ; while (n) {
if (n & )
ret *= base;
n >>= ;
base *= base;
} return ret;
} void solve() {
double ans = 0.0; if (op) {
double tmp = 1.0;
rep(i, , n) {
tmp = tmp * m / (m-i);
ans += tmp;
}
} else {
LL fz = Pow(m, n) - ;
ans = fz / (m-);
}
printf("%.9lf\n", ans);
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif while (scanf("%d", &t)!=EOF) {
while (t--) {
scanf("%d%d%d", &op, &m, &n);
solve();
}
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}