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;
}
posted @ 2025-11-28 09:55  Hengsber  阅读(4)  评论(0)    收藏  举报