注释写明了一切
#include <cstdio> #define N 111 #define p 9999973 #define LL long long int n, m; LL ans, f[N][N][N]; //每一行和每一列可以放0/1/2个炮 //f[i][j][k]表示前i行放了1个炮的列有j个,放了2个炮的列有k个的方案数 //那么可以推出,放了0个炮的列有m-j-k个 inline int C(int x) { return x * (x - 1) / 2; } int main() { int i, j, k, l; scanf("%d %d", &n, &m); f[0][0][0] = 1; for(i = 1; i <= n; i++) for(j = 0; j <= m; j++) for(k = 0; k <= m - j; k++) { //当前这一行不放炮 f[i][j][k] += f[i - 1][j][k]; //当前这一行就放一个炮 //放到没有炮的列 if(j) f[i][j][k] += (m - k - j + 1) * f[i - 1][j - 1][k]; //放到有炮的列 if(k) f[i][j][k] += (j + 1) * f[i - 1][j + 1][k - 1]; //当前这一行放两个炮 //放到两个没有炮的列 if(j >= 2) f[i][j][k] += C(m - k - j + 2) * f[i - 1][j - 2][k]; //放到两个有炮的列 if(k >= 2) f[i][j][k] += C(j + 2) * f[i - 1][j + 2][k - 2]; //放到一个有炮的列,一个没有炮的列 if(j && k) f[i][j][k] += j * (m - j - k + 1) * f[i - 1][j][k - 1]; f[i][j][k] %= p; } for(i = 0; i <= m; i++) for(j = 0; j <= m - i; j++) ans = (ans + f[n][i][j]) % p; printf("%lld ", ans); return 0; }