2019 ICPC 亚洲区域赛银川场 B. So Easy:题解|刷题打卡

·  阅读 163

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述:

今天我们来写一道简单题吧,这道题的名字就叫做So Easy,是 2019 ICPC 亚洲区域赛银川场的 B 题。

image.png

题目大意:

有一个 n×nn \times n 的矩阵,开始的时候每个元素都是 00,每一步操作都必须选择某一行或某一列,将这一行的元素全都加上一个正数,经过若干步后得到了结果矩阵。

现在给你这个结果矩阵,但是其中的某一个元素被修改成了 1-1,要你找出它被修改成 1-1 前是多少。

二、思路分析:

由于每次修改的都是一整行或一整列,我们可以发现最后得到元素的值就是它所在列加上的数和它所在行加上的数之和。设 1-1 所在行为 rowrow,所在列为 colcol,令 s[i]s[i] 表示 ii 行所加上的数,t[i]t[i] 表示第 ii 列上所加的数,那么我们自然会像要去求 s[row]s[row]t[row]t[row],但是很可惜这两个值无法通过某一行或某一列求出,因为每个元素都受到其所在行和列加上的数的影响,就导致了最终产生的每一行的元素都受到了每一列所加数的影响。

所以我们就要另寻他法。用 mm 表示结果矩阵,通过观察我们可以发现 m[row][col]=s[row]+t[col]m[row][col] = s[row] + t[col] 等式右边的两个加数来自不同的类别,如果能够消去一个缩小考虑的范围就好了。这个时候可以想到用同一行/列的元素的元素相减,比如 m[row][col]m[x][col]=s[row]+t[col]s[x]t[col]=s[row]s[x]m[row][col] - m[x][col] = s[row] + t[col] - s[x] - t[col] = s[row] - s[x],我们可以发现同一列元素的差值就是它们所在行所加数的差值,这样一来我们就可以任意选择一个元素 m[x][y]m[x][y],利用它推出答案。推导过程如下:

m[row][col]=m[x][y]+s[row]s[x]+t[row]t[y]=m[x][y]+m[row][y]m[x][y]+m[x][col]m[x][y]=m[row][y]+m[x][col]m[x][y]\begin{aligned} m[row][col] &= m[x][y] + s[row] - s[x] + t[row] - t[y]\\ &= m[x][y] + m[row][y] - m[x][y] + m[x][col] - m[x][y]\\ &= m[row][y] + m[x][col] - m[x][y] \end{aligned}

三、AC 代码:

#include <iostream>
using namespace std;
const int maxn = 1005;
int m[maxn][maxn];

int main() {
    int n;
    scanf("%d", &n);
    int row, col, x = 0, y;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            scanf("%d", m[i] + j);
            if (m[i][j] == -1) {
                row = i, col = j;
            }
        }
    }
    if (m[0][0] == -1) {
        y = 1;
    } else {
        y = 0;
    }
    printf("%d\n", m[x][y] + m[row][y] + m[x][col] - m[x][y]);
}
复制代码

四、总结:

这道题应该算是典型的公式推导题吧,只要消去同类项就可以很容易看出规律。所以以后遇到复杂的公式先不要着急写,有可能化简一下公式答案就出来了。

分类:
代码人生
标签:
分类:
代码人生
标签:
收藏成功!
已添加到「」, 点击更改