HDU 5155 Harry And Magic Box(dp+组合数学)

题目链接

题目大意

  有个n*m的矩阵,从他的四条边看去都有数,问有多少种可能。

解题思路

  利用dp来求解,设dp[i][j]为\(i\times j\)矩阵的答案。那么对于一个i行j列的矩阵,我们可以拿之前\(1\times (j-1)\)的矩阵来做,然后将其和剩下的空行排列组合,为了保证空行的j-1列还是空行,但是到第j列不是,那么都要在空行的第j列加上一格,那么剩下的可以放的位置就是那些\(1\times (j-1)\)的矩阵第j列的位置,注意有一种特殊情况,当所有的\(1\times (j-1)\)的矩阵之前的行都有物品的时候,第j列要排除一个物品也不放的情况。可以参考下图:

  dp转移方程为\(dp[i][j] = dp[i][j-1]\times \tbinom{i}{i} \times (2^i-1) +\sum_{k=1}^{i-1} dp[k][j-1]\times \tbinom{i}{k} \times 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;
}
posted @ 2020-08-28 23:50  shuitiangong  阅读(160)  评论(0编辑  收藏  举报