現有n個m面的骰子,Ujisato要擲這些骰子,他所獲得的鈔票數是這些骰子的點數之和減去k。而且即使點數之和小於k,Ujisato也能得到一張鈔票。假設骰子的每一面的點數爲1到m,投得每一面的概率是相等的。
動態規劃思想:
設dp[i%2][j]表示投第i(0<=i<n)個骰子時,骰子點數之和爲j總共有多少種情況。
#include<iostream>
#include<vector>
#include<math.h>
#include<stdio.h>
using namespace std;
int main(){
int n, m, k;
while(cin >> n >> m >> k){
if(n == 0 && m == 0 && k == 0)
break;
vector<vector<int> > dp(2);
dp[0].resize(n*m+1);
dp[1].resize(n*m+1);
dp[0][0] = 0;
for(int i = 1; i <= m; ++i)
dp[0][i] = 1;
for(int i = m+1; i <= n*m; ++i)
dp[0][i] = 0;
for(int i = 1; i < n; ++i){
for(int j = 0; j <= n*m; ++j)
dp[i%2][j] = 0;
for(int p = 1; p <= n*m; ++p)
for(int j = 1; j <= m && j < p; ++j)
dp[i%2][p] += dp[1-i%2][p-j];
}
int sum = 0;
for(int i = 1; i <=k ; ++i)
sum += dp[(n-1)%2][i];
for(int i = k+1; i <= n*m; ++i)
sum += (i-k)*dp[(n-1)%2][i];
int total = pow(1.0*m, 1.0*n);
double ans = (double)(1.0*sum)/total;
printf("%.8f\n", ans);
}
return 0;
}