dp[i][j][k]表示前i步覆盖j列k行的概率。
#include <iostream>
#include<stdio.h>
using namespace std;
double dp[2600][55][55];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d %d",&n,&m);
for(int i = 0;i <= n*m;i++)
for(int j = 0;j <= m;j++)
for(int k = 0;k <= n;k++)
dp[i][j][k] = 0;
dp[0][0][0] = 1;
dp[1][1][1] = 1;
for(int i = 2;i <= n*m;i++)
for(int j = 1;j <= m;j++)
for(int k = 1;k <= n;k++)
{
double tmp = m*n - i +1;
dp[i][j][k] += dp[i-1][j-1][k]*((m-j+1)*k*1.0/tmp) + dp[i-1][j][k-1]*((n-k+1)*j*1.0/tmp)
+dp[i-1][j-1][k-1]*(1.0*(m-j+1)*(n-k+1)/tmp);
if( j == m && k == n) continue;
dp[i][j][k]+=dp[i-1][j][k]*(j*k-i+1)*1.0/tmp;
}
double ans = 0;
for(int i = 1;i <= n*m;i++)
{
if(dp[i][m][n] - 0 < 0.00000000001) continue;
ans+=i*1.0*dp[i][m][n];
}
printf("%.12lf\n",ans);
}
return 0;
}