CF2145
CF2145G Cost of Coloring
肯定是关注这个最小步数。根据题意,我们肯定是先染小的,然后再染大的,所以小的一些肯定会被盖起来。我们反过来思考这个流程,就相当于对于 \(a_i > 1\) 的那些行/列,我们把他们删除。最后剩一个 \(x \times y\) 的 \(a_i = 1\) 的矩形,这样总的步数就是 \(n - x + m - y + \min(x, y)\),意思是我们要把 \(n - x + m - y\) 行/列删掉,然后再加上染 \(x \times y\) 的矩形需要的最小步数。
然后就好做了,枚举 \(x, y\)。然后把 \(n - x + m - y\) 行/列分到 \(k - 1\) 个颜色中去,再乘上染 1 的方案,答案就是 \({n - x + m - y \brace k - 1}(k - 1)!\binom{n}{x}\binom{m}{y}\) 贡献到 \(ans_{n - x + m - y + \min(x, y)}\)。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 4e3 + 5, mod = 998244353;
ll c[N][N], s[N][N], fac[N], ans[N];
void add(ll &x, ll y){ (x += y) %= mod; }
int main(){
cin.tie(0)->sync_with_stdio(0);
fac[0] = c[0][0] = s[0][0] = 1;
for(int i = 1; i <= 4e3; ++i){
c[i][0] = 1; fac[i] = fac[i - 1] * i % mod;
for(int j = 1; j <= i; ++j){
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
s[i][j] = (s[i - 1][j - 1] + j * s[i - 1][j]) % mod;
}
}
int n, m, k;
cin >> n >> m >> k;
for(int x = 1; x <= n; ++x){
for(int y = 1; y <= m; ++y){
int p = n + m - x - y;
add(ans[p + min(x, y)], c[n][x] * c[m][y] % mod * s[p][k - 1] % mod * fac[k - 1] % mod);
}
}
for(int i = min(n, m); i <= n + m - 1; ++i) cout << ans[i] << ' ';
return 0;
}

浙公网安备 33010602011771号