dp[i][j]: 前 i 行 满足每一行都有 1 且满足有 j 列有1,考虑第i行的放置情况状态转移:
memset(dp, 0, sizeof dp);
dp[0][0] = 1LL;
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
for(int k = 0; k <= m; ++k) {
if(dp[i - 1][k] != 0) {
for(int t = j; t <= m && t <= k + j; ++t) {
// t1 is new added while t2 must selected from j
int t1 = t - k, t2 = j - t1;
long long tmp = C[m - k][t1] * C[k][t2] % mod;
// t >= j, enumerate all Combination of t
dp[i][t] = (dp[i][t] + dp[i - 1][k] * tmp % mod) % mod;
}
}
}
}
}