题解

1 条题解

  • 1
    @ 2024-10-05 20:02:25

    题意:

    给定一个矩阵,定义两个子矩阵互为友矩阵当且仅当:
    1. 权值和相等。
    2. 左上角在同一个点。
    3. 右下角不在同一个点。
    4. 长加宽之和相等。
    5. 长减宽之差互为相反数。
    - 求给定矩阵上长为 a 宽为 b 的权值和最大的子矩阵的权值和。
    - \(1 \leq n, m \leq 1000, 1 \leq a < n, 1 \leq b < m, \lvert Ai,j \rvert \leq 1919810\)。

    \(
    S =
    \begin{bmatrix}
    a_{1, 1} & a_{1, 2} & \cdots & a_{1, n - 1} & a_{1, n} \cr
    a_{2, 1} & a_{2, 2} & \cdots & a_{2, n - 1} & a_{2, n} \cr
    \vdots & \vdots & \ddots & \vdots & \vdots \cr
    a_{m - 1, 1} & a_{m - 1, 2} & \cdots & a_{m - 1, n - 1} & a_{m - 1, n} \cr
    a_{m, 1} & a_{m, 2} & \cdots & a_{m, n - 1} & a_{m, n} \cr
    \end{bmatrix}
    \)

    很明显,由条件 \(4\) 和条件 \(5\) 可得一个方程组:

    \[
    \begin{aligned}
    & \begin{cases}
    (r_{A, x} - l_{A, x}) + (r_{A, y} - l_{A, y}) = (r_{B, x} - l_{B, x}) + (r_{B, y} - l_{B, y}) \\
    (r_{A, x} - l_{A, x}) - (r_{A, y} - l_{A, y}) + (r_{B, x} - l_{B, x}) - (r_{B, y} - l_{B, y}) = 0
    \end{cases}
    \cr
    & 解得:
    \begin{cases}
    r_{A, x} - l_{A, x} = r_{B, y} - l_{B, y} \\
    r_{A, y} - l_{A, y} = r_{B, x} - l_{B, x}
    \end{cases}
    \end{aligned}
    \]

    又因为\(
    \begin{cases}
    r_{A, x} - l_{A, x} = a\\
    r_{A, y} - l_{A, y} = b
    \end{cases}
    \),于是,进一步我们可知 \(A\) 的长等于 \(B\) 的宽等于 \(a\),\(A\) 的宽等于 \(B\) 的长等于 \(b\);

    而又由于性质 \(2\),左上角的点被直接确定,因此对于每个矩阵,它可能的友矩阵都是唯一的。

    即有:

    \[
    A = \begin{bmatrix}
    a_{x_1. y_1} & \cdots & a_{x_1 + a - 1, y_1} \\
    \vdots & \ddots & \vdots \\
    a_{x_1, y_1 + b - 1} & \cdots & a_{x_1 + a - 1, y_1 + b - 1}
    \end{bmatrix}
    \]
    \[
    \text{and}
    \]
    \[
    B = \begin{bmatrix}
    a_{x_2. y_2} & \cdots & a_{x_2 + b - 1, y_2} \\
    \vdots & \ddots & \vdots \\
    a_{x_2, y_2 + a - 1} & \cdots & a_{x_2 + b - 1, y_2 + a - 1}
    \end{bmatrix}
    \]

    那我们又如何快速求矩阵的权值和呢?

    我们想到使用二维前缀和,每次查询两个子矩阵的和是否相等即可,若相等则更新答案。

    #include <iostream>
    using namespace std;
    typedef long long ll;
    
    ll read() {
        ll x = 0, f = 1;
        char ch = getchar();
        for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
        for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
        return x * f;
    }
    
    static const int N = 1010;
    
    ll pre[N][N];
    
    ll get_sum(ll x, ll y, ll a, ll b) {
        return pre[x + a - 1][y + b - 1] - pre[x - 1][y + b - 1] - pre[x + a - 1][y - 1] + pre[x - 1][y - 1];
    }
    
    int main() {
        ll n = read(), m = read(), a = read(), b = read();
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++) {
                ll x = read();
                pre[i][j] = x + pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1];
            }
        
        ll ans = -1145141919810;
        for (int i = 1; i + max(a, b) - 1 <= n; i++)
            for (int j = 1; j + max(a, b) - 1 <= m; j++) {
                ll suma = get_sum(i, j, a, b), sumb = get_sum(i, j, b, a);
                if (suma == sumb) ans = max(ans, suma);
            }
        
        if (ans == -1145141919810) cout << "Chinese_zjc_ L\n";
        else cout << ans << '\n';
        return 0;
    }
    
  • 1

信息

ID
1072
难度
(无)
分类
数学 点击显示
标签
(无)
递交数
0
已通过
0
通过率
?
上传者