Codeforcesラウンド#589(DIV 2)E.別充填グリッド(DP、組合せ論)

リンク:

https://codeforces.com/contest/1228/problem/E

質問の意味:

あなたはn個のn正方格子と整数kを×しています。以下の条件を満足しつつ、各セル内の整数を置きます。

グリッド内のすべての数字は1とkの包括的であるべきです。
i番目の行の最小数は1(1≤i≤n)です。
j番目の列の最小数は1(1≤j≤n)です。
グリッド内の整数を置くために、いくつかの方法を探します。答えは非常に大きくなる可能性があるので、回答モジュロ(109 + 7)を見つけます。

これらは、有効と無効グリッドN = K = 2の例です。

アイデア:

DP [I] [j]が転送上下ランクの数に等しい場合、各ライン1は、転送を考慮することを確保しながら、iおよび列jが1である最前列を有している。
、単独で考えると、カラム1は、任意の値であってもよいが1で現在の行1の保証がなければなりません。

コード:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MOD = 1e9+7;

LL C[300][300];
LL Dp[300][300];
LL M1[300], M2[300];
LL n, k;

int main()
{
    C[0][0] = C[1][0] = C[1][1] = 1;
    for (int i = 2;i <= 250;i++)
    {
        C[i][0] = C[i][i] = 1;
        for (int j = 1;j < i;j++)
            C[i][j] = (C[i-1][j]+C[i-1][j-1])%MOD;
    }
    M1[0] = M2[0] = 1;
    cin >> n >> k;
    for (int i = 1;i <= n;i++)
        M1[i] = (M1[i-1]*k)%MOD, M2[i] = (M2[i-1]*(k-1))%MOD;
    //k^i
    for (int i = 1;i <= n;i++)
        Dp[1][i] = (C[n][i]*M2[n-i])%MOD;
    for (int i = 2;i <= n;i++)
    {
        for (int j = 1;j <= n;j++)
        {
            for (int p = j;p <= n;p++)
            {
                LL res = ((C[n-j][p-j]*M2[n-p])%MOD*M1[j])%MOD;
                if (p == j)
                    res = ((M1[j]-M2[j])*M2[n-j])%MOD;
                LL sum = (Dp[i-1][j]*res)%MOD;
                Dp[i][p] = (Dp[i][p]%MOD + sum + MOD)%MOD;
            }
        }
    }
    cout << Dp[n][n] << endl;

    return 0;
}

おすすめ

転載: www.cnblogs.com/YDDDD/p/11620467.html