题目大意
有个n*m的矩阵,从他的四条边看去都有数,问有多少种可能。
解题思路
利用dp来求解,设dp[i][j]为(i imes j)矩阵的答案。那么对于一个i行j列的矩阵,我们可以拿之前(1 imes (j-1))的矩阵来做,然后将其和剩下的空行排列组合,为了保证空行的j-1列还是空行,但是到第j列不是,那么都要在空行的第j列加上一格,那么剩下的可以放的位置就是那些(1 imes (j-1))的矩阵第j列的位置,注意有一种特殊情况,当所有的(1 imes (j-1))的矩阵之前的行都有物品的时候,第j列要排除一个物品也不放的情况。可以参考下图:
dp转移方程为(dp[i][j] = dp[i][j-1] imes binom{i}{i} imes (2^i-1) +sum_{k=1}^{i-1} dp[k][j-1] imes binom{i}{k} imes 2^k)
代码
const int maxn = 50+10;
const int maxm = 2e2+10;
ll dp[maxn][maxn], c[maxn][maxn], mi[maxn] = {1}; int n, m;
int main() {
for (int i = 1; i<maxn; ++i)
c[i][i] = c[i][0] = 1, mi[i] = mi[i-1]*2LL%MOD;
for (int i = 2; i<maxn; ++i)
for (int j = 1; j<i; ++j)
c[i][j] = (c[i-1][j-1]+c[i-1][j])%MOD;
for (int i = 1; i<maxn; ++i) dp[1][i] = dp[i][1] = 1;
for (int i = 2; i<maxn; ++i)
for (int j = 2; j<maxn; ++j) {
dp[i][j] = dp[i][j-1]*(mi[i]-1)%MOD;
for (int k = 1; k<i; ++k) dp[i][j] = (dp[i][j]+dp[k][j-1]*c[i][k]%MOD*mi[k]%MOD)%MOD;
}
while(cin >> n >> m) cout << dp[n][m] << endl;
return 0;
}