参考:
http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710606.html
http://blog.csdn.net/roney_win/article/details/9822753
const int MAXN = 1010;
double dp[MAXN][MAXN];
/***
markov,
dp[i][j]表示已经找到i种bug,j个系统的bug,达到目标状态的天数的期望,即从dp[i][j]到dp[n][s]的天数的期望
dp[n][s]=0;要求的答案是dp[0][0];
dp[i][j]可以转化成以下四种状态:
dp[i][j],发现一个bug属于已经有的i个分类和j个系统。概率为(i/n)*(j/s);
dp[i][j+1],发现一个bug属于已有的分类,不属于已有的系统.概率为 (i/n)*(1-j/s);
dp[i+1][j],发现一个bug属于已有的系统,不属于已有的分类,概率为 (1-i/n)*(j/s);
dp[i+1][j+1],发现一个bug不属于已有的系统,不属于已有的分类,概率为 (1-i/n)*(1-j/s);
则倒着递推即可
*/
int main ()
{
int n, s;
while (~RII(n, s))
{
dp[n][s] = 0;
for (int i = n; i >= 0; i--)
{
for (int j = s; j >= 0; j--)
{
if (i == n && j == s) continue;
dp[i][j]=(i*(s-j)*dp[i][j+1]+(n-i)*j*dp[i+1][j]+(n-i)*(s-j)*dp[i+1][j+1]+n*s)/(n*s-i*j);
}
}
printf("%.4lf\n", dp[0][0]);
}
return 0;
}