解题思路:
简单的DP , 用DP[ i ] [ j ] [ k ] 表示第 i 天 覆盖了 j 行 k 列 的概率 , 递推公式很容易得出 , 然后利用期望的定义求出ans。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#define LL long long
#define FOR(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
const int MAXN = 55;
double dp[MAXN * MAXN][MAXN][MAXN];
int N , M;
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>N>>M;
memset(dp , 0 , sizeof(dp));
dp[0][0][0] = 1;
for(int i=1;i<=N*M-min(N,M)+1;i++)
{
for(int j=1;j<=i&&j<=N;j++)
{
for(int k=1;k<=i&&k<=M;k++)
{
if(j == N && k == M) dp[i][j][k] = (dp[i-1][j-1][k] * (double)(k*(N-j+1)) / (double)((N*M-i+1)) +
dp[i-1][j][k-1]*(double)(j*(M-k+1)) / (double)(N*M-i+1) + dp[i-1][j-1][k-1] * (double)((M-k+1)*(N-j+1))/(double)(N*M-i+1));
else dp[i][j][k] = (dp[i-1][j-1][k] * (double)(k*(N-j+1)) / (double)((N*M-i+1)) +
dp[i-1][j][k-1]*(double)(j*(M-k+1)) / (double)(N*M-i+1) + dp[i-1][j-1][k-1] * (double)((M-k+1)*(N-j+1))/(double)(N*M-i+1)
+dp[i-1][j][k] * (double)((k*j-i+1) / (double)((N*M-i+1))));
}
}
}
double ans = 0;
for(int i=1;i<=N*M-min(N,M)+1;i++)
{
ans += (dp[i][N][M] * i);
}
printf("%.12lf\n",ans);
}
return 0;
}