リンク:
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;
}