• Solution 「AGC 039F」Min Product Sum


    \(\mathscr{Description}\)

      Link.

      对于所有 \(n\times m\) 的矩阵 \(A\), \(a_{ij}\in[1,k]\cap\mathbb N\), 求

    \[\sum_A\prod_{i,j}\min\left\{\min_{t=1}^m\{a_{it}\},\min_{t=1}^n\{a_{tj}\}\right\}\bmod P. \]

      \(n,m,k\le100\), \(P\) 为素数.

    \(\mathscr{Solution}\)

      很有想象力的状态设计, 不愧是 AGC. (

      (下令题面中 \(k\)\(d\), \(k\) 另作他用.) 第一步是技巧性的转化: 把所有 "权值" 构造成方案数, 将问题变为纯纯的方案数计数问题. 这里不难将 \(A\) 的权值描述为满足 \(1\le b_{ij}\le a_{ij}\) 的矩阵 \(B\) 的数量. 我们就是要求所有 \((A,B)\) 的方案.

      令 \(f(i,j,k)\) 表示考虑了所有 \(B\) 中最大值 \(\in[1,i]\) 行列以及 \(A\) 中所有最小值 \(\in[1,i]\) 的行列, 总共有 \(j\) 行被考虑到, \(k\) 列被考虑到时, 所有可确定位置的方案数之和. 注意, 对于每个位置, 当其第一次被行 (或列) 考虑到时, 我们先确定其 \(B\) 中的值; 当其接着被列 (或行) 考虑到时, 我们再确定其 \(A\) 中的值.

      转移不妨先填出最小值为 \(i\) 的行, 再填出最小值为 \(i\) 的列.

      填行, 对于新被考虑到的一行:

    • \(k\) 个位置在填 \(A\) 值. 因为本行最小值钦定为 \(i\), 所以方案数为 \((d-i+1)^k\).
    • \(m-k\) 个位置在填 \(B\) 值. 同理, 方案数为 \(i^{m-k}-(i-1)^{m-k}\) (容斥使得至少有一个 \(i\), 限定新行上取出 \(B\) 的行最大值为 \(i\)).

      填列, 对于新被考虑到的一列:

    • \(j\) 个位置在填 \(A\) 值. 方案数为 \((d-i+1)^j-(d-i)^j\) (容斥使得至少有一个 \(i\), 限定新列上取出 \(A\) 的列最大值为 \(i\)).
    • \(n-j\) 个位置在填 \(B\) 值. 方案数为 \(i^{n-j}\).

      两个不那么对称的容斥限定使得 "新建行列上有 [\(B\) 的最大值 \(i\) / \(A\) 的最小值 \(i\) / 二者]" 三种情况都能唯一地取出来. 那么枚举每次新建的行列数量, 可以做到 \(\mathcal O(nmk(n+m))\) 转移求解.

    \(\mathscr{Code}\)

    /*+Rainybunny+*/
    
    #include <bits/stdc++.h>
    
    #define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
    #define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)
    
    const int MAXN = 100;
    int n, m, d, P, bino[MAXN + 5][MAXN + 5], f[2][MAXN + 5][MAXN + 5];
    
    inline int mul(const int u, const int v) { return 1ll * u * v % P; }
    inline void subeq(int& u, const int v) { (u -= v) < 0 && (u += P); }
    inline int sub(int u, const int v) { return (u -= v) < 0 ? u + P : u; }
    inline void addeq(int& u, const int v) { (u += v) >= P && (u -= P); }
    inline int add(int u, const int v) { return (u += v) < P ? u : u - P; }
    inline int mpow(int u, int v) {
        int ret = 1;
        for (; v; u = mul(u, u), v >>= 1) ret = mul(ret, v & 1 ? u : 1);
        return ret;
    }
    
    inline void init() {
        bino[0][0] = 1;
        rep (i, 1, MAXN) {
            bino[i][0] = 1;
            rep (j, 1, i) bino[i][j] = add(bino[i - 1][j - 1], bino[i - 1][j]);
        }
    }
    
    int main() {
        scanf("%d %d %d %d", &n, &m, &d, &P);
        init();
    
        f[0][0][0] = 1;
        rep (i, 1, d) {
            auto fcur = f[0], fnex = f[1];
            rep (j, 0, n) rep (k, 0, m) {
                if (int& cur = fcur[j][k]) {
                    int pw = 1, c = mul(sub(mpow(i, m - k),
                      mpow(i - 1, m - k)), mpow(d - i + 1, k));
                    rep (l, 0, n - j) {
                        addeq(fnex[j + l][k], mul(mul(bino[repl][l], pw), cur));
                        pw = mul(pw, c);
                    }
                    cur = 0;
                }
            }
            
            fcur = f[1], fnex = f[0];
            rep (j, 0, n) rep (k, 0, m) {
                if (int& cur = fcur[j][k]) {
                    int pw = 1, c = mul(sub(mpow(d - i + 1, j),
                      mpow(d - i, j)), mpow(i, n - j));
                    rep (l, 0, m - k) {
                        addeq(fnex[j][k + l], mul(mul(bino[repl][l], pw), cur));
                        pw = mul(pw, c);
                    }
                    cur = 0;
                }
            }
        }
        printf("%d\n", f[0][n][m]);
        return 0;
    }
    
    
  • 相关阅读:
    Yii框架2.0 数据库操作初接触
    Yii框架2.0的视图和widgets表单的使用
    Yii框架2.0的安装过程
    监控之snmpd 服务
    在HTML里面HEAD部分的META元素要表达的内容是什么
    被table单元格colspan属性折磨了
    excel模版从xp复制到win7系统后出现错误 运行时错误 '429' ActiveX 部件不能创建对象
    oracle左连接连表查询
    Nginx 关闭防火墙
    左连接不能与or否则in连用
  • 原文地址:https://www.cnblogs.com/rainybunny/p/16500036.html
Copyright © 2020-2023  润新知