对于一个矩阵,定义函数 f(x,y) 为:第 x 行和第 y 列的一共 N+M−1 个数中的最小值。
对于一个矩阵,定义其权值为 x=1∏Ny=1∏Mf(x,y)。
你需要求出,对于所有 KNM 种矩阵,每个矩阵的权值和对 D 取模的结果。
1≤N,M,K≤100,108≤D≤109,保证 D 为质数。
Solution
首先设矩阵为 b,ci 表示 b 第 i 行的最小值,dj 表示 b 第 j 列的最小值,它的权值可以转化为有多少个矩阵 a,满足:ai,j≤min{ci,dj},也就是说 a 的第 i 行最大值小于等于 ci 且 a 的第 j 行最大值小于等于 dj,同时显然需要满足 bi,j≥max{ci,dj}。
int n, m, k, mod; int f[kMaxN][kMaxN], C[kMaxN][kMaxN];
intqpow(int bs, int64_t idx = mod - 2){ int ret = 1; for (; idx; idx >>= 1, bs = (int64_t)bs * bs % mod) if (idx & 1) ret = (int64_t)ret * bs % mod; return ret; }
inlineintadd(int x, int y){ return (x + y >= mod ? x + y - mod : x + y); } inlineintsub(int x, int y){ return (x >= y ? x - y : x - y + mod); } inlinevoidinc(int &x, int y){ (x += y) >= mod ? x -= mod : x; } inlinevoiddec(int &x, int y){ (x -= y) < 0 ? x += mod : x; }
voidprework(){ C[0][0] = 1; for (int i = 1; i <= std::max(n, m); ++i) { C[i][0] = 1; for (int j = 1; j <= i; ++j) C[i][j] = add(C[i - 1][j], C[i - 1][j - 1]); } }
voiddickdreamer(){ std::cin >> n >> m >> k >> mod; prework(); f[0][0] = 1; for (int v = 1; v <= k; ++v) { for (int i = n; ~i; --i) { for (int j = m; ~j; --j) { int val = 1ll * sub(qpow(v, m - j), qpow(v - 1, m - j)) * qpow(k - v + 1, j) % mod, coef = 1; for (int w = 1; w <= i; ++w) { coef = 1ll * coef * val % mod; inc(f[i][j], 1ll * f[i - w][j] * C[n - i + w][w] % mod * coef % mod); } } } for (int i = n; ~i; --i) { for (int j = m; ~j; --j) { int val = 1ll * qpow(v, n - i) * sub(qpow(k - v + 1, i), qpow(k - v, i)) % mod, coef = 1; for (int w = 1; w <= j; ++w) { coef = 1ll * coef * val % mod; inc(f[i][j], 1ll * f[i][j - w] * C[m - j + w][w] % mod * coef % mod); } } } } std::cout << f[n][m] << '\n'; }