【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. 代码

 1 /* 4652 */
 2 #include <iostream>
 3 #include <sstream>
 4 #include <string>
 5 #include <map>
 6 #include <queue>
 7 #include <set>
 8 #include <stack>
 9 #include <vector>
10 #include <deque>
11 #include <bitset>
12 #include <algorithm>
13 #include <cstdio>
14 #include <cmath>
15 #include <ctime>
16 #include <cstring>
17 #include <climits>
18 #include <cctype>
19 #include <cassert>
20 #include <functional>
21 #include <iterator>
22 #include <iomanip>
23 using namespace std;
24 //#pragma comment(linker,"/STACK:102400000,1024000")
25 
26 #define sti                set<int>
27 #define stpii            set<pair<int, int> >
28 #define mpii            map<int,int>
29 #define vi                vector<int>
30 #define pii                pair<int,int>
31 #define vpii            vector<pair<int,int> >
32 #define rep(i, a, n)     for (int i=a;i<n;++i)
33 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
34 #define clr                clear
35 #define pb                 push_back
36 #define mp                 make_pair
37 #define fir                first
38 #define sec                second
39 #define all(x)             (x).begin(),(x).end()
40 #define SZ(x)             ((int)(x).size())
41 #define lson            l, mid, rt<<1
42 #define rson            mid+1, r, rt<<1|1
43 
44 #define LL __int64
45 
46 int t;
47 int op, n, m;
48 
49 LL Pow(LL base, int n) {
50     LL ret = 1;
51     
52     while (n) {
53         if (n & 1)
54             ret *= base;
55         n >>= 1;
56         base *= base;
57     }
58     
59     return ret;
60 }
61 
62 void solve() {
63     double ans = 0.0;
64     
65     if (op) {
66         double tmp = 1.0;
67         rep(i, 0, n) {
68             tmp = tmp * m / (m-i);
69             ans += tmp;
70         }
71     } else {
72         LL fz = Pow(m, n) - 1;
73         ans = fz / (m-1);
74     }
75     printf("%.9lf\n", ans);
76 }
77 
78 int main() {
79     ios::sync_with_stdio(false);
80     #ifndef ONLINE_JUDGE
81         freopen("data.in", "r", stdin);
82         freopen("data.out", "w", stdout);
83     #endif
84     
85     while (scanf("%d", &t)!=EOF) {
86         while (t--) {
87             scanf("%d%d%d", &op, &m, &n);
88             solve();
89         }
90     }
91     
92     #ifndef ONLINE_JUDGE
93         printf("time = %d.\n", (int)clock());
94     #endif
95     
96     return 0;
97 }

 

你可能感兴趣的:(【HDOJ】4652 Dice)