1. 题目描述
对于m面的骰子。有两种查询,查询0表示求最后n次摇骰子点数相同的期望;查询1表示最后n次摇骰子点数均不相同的期望。
2. 基本思路
由期望DP推导,求得最终表达式。
(1) 查询0
不妨设$dp[k]$表示当前已经有k次相同而最终实现n次相同的期望。
egin{align}
dp[0] &= 1 + dp[1]
otag \
dp[1] &= 1 + frac{1}{m}dp[2] + frac{m-1}{m}dp[1]
otag \
dp[2] &= 1 + frac{1}{m}dp[3] + frac{m-1}{m}dp[1]
otag \
&cdots
otag \
dp[n-1] &= 1 + frac{1}{m}dp[n] + frac{m-1}{m}dp[1]
otag \
dp[n] &= 0
end{align}
两两相减可得。
egin{align}
dp[0]-dp[1] &= frac{1}{m}(dp[1]-dp[2])
otag \
dp[1]-dp[2] &= frac{1}{m}(dp[2]-dp[3])
otag \
dp[2]-dp[3] &= frac{1}{m}(dp[3]-dp[4])
otag \
&cdots
otag \
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$代入可得。
egin{align}
dp[0]-dp[1] &= 1
otag \
dp[1]-dp[2] &= m
otag \
dp[2]-dp[3] &= m^2
otag \
&cdots
otag \
dp[n-1]-dp[n] &= m^{n-1}
end{align}
显然是一个等比数列,累加后可得$dp[0]-dp[n]=dp[0]$.
egin{align}
dp[0] = frac{m^n-1}{m-1}
end{align}
(2)查询1
不妨设$dp[k]$表示当前已经有k个不同而最终实现n个不同的期望。
egin{align}
dp[0] &= 1 + dp[1]
otag \
dp[1] &= 1 + frac{1}{m}dp[1] + frac{m-1}{m}dp[2]
otag \
dp[2] &= 1 + frac{1}{m}dp[1] + frac{1}{m}dp[2] + frac{m-2}{m}dp[3]
otag \
&cdots
otag \
dp[n-1] &= 1 + Sigma_{i=1}^{n-1}{frac{1}{m}dp[i]} + frac{m-(n-1)}{m}dp[n]
otag \
dp[n] &= 0
end{align}
两两相减可得。
egin{align}
dp[0]-dp[1] &= frac{m-1}{m}(dp[1]-dp[2])
otag \
dp[1]-dp[2] &= frac{m-2}{m}(dp[2]-dp[3])
otag \
&cdots
otag \
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$代入累加后可得。
egin{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 ", 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. ", (int)clock()); 94 #endif 95 96 return 0; 97 }