题意:给出n个有m面的骰子,扔一次,求出和,如果和小于等于k,就记1,否则就是和减去k,求最后期望。

题解:用滚动数组dp[2][MAX]记录当前扔到某个数的情况种数,然后......挺水的。。

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 const int N=10005;
 7 int dp[2][N];
 8 int main()
 9 {
10     int n,m,k;
11     while(scanf("%d%d%d",&n,&m,&k),n||m||k)
12     {
13         double all=pow((double)m,double(n));
14         memset(dp,0,sizeof(dp));
15         for(int i=1;i<=m;i++)
16             dp[0][i]=1;
17         int mmax=n*m;
18         double sum=0;
19         for(int i=2;i<=n;i++)
20         {
21             int a=i&1,b=a^1;
22             memset(dp[b],0,sizeof(dp[b]));
23             for(int j=mmax;j>=1;j--)
24                 for(int t=1;t<=m&&t<j;t++)
25                     dp[b][j]+=dp[a][j-t];
26         }
27         int no=(n+1)&1;
28         for(int i=1;i<=k+1;i++)
29             sum+=(double)dp[no][i];
30         for(int i=k+2;i<=mmax;i++)
31             sum+=(double)dp[no][i]*(i-k);
32         printf("%.8lf\n",sum/all);
33     }
34     return 0;
35 }