【矩阵压缩】codeforces 1980 E. Permutation of Rows and Columns
题目链接
https://codeforces.com/problemset/problem/1980/E
题意
共输入
接下来输入两个
你有以下两种可以执行的操作:
- 选择两个不同的行进行交换
- 选择两个不同的列进行交换
你可以执行上述操作任意次,每次只能选择其中一个操作。问:能否通过上述操作将矩阵
题解
本质是考察线性代数的相等矩阵的知识。
矩阵相等的条件:
- 两个矩阵为同型矩阵
- 矩阵的元素完全相同
对于条件1,由于矩阵
对于条件2,只能使用选择两个不同的行/列进行交换,去尝试使之成立
对于初等行/列变换中的行/列交换,有一个非常重要的性质,就是进行行(列)交换后,行(列)内元素的相对位置不会发生变化。
基于上述性质,假设此时发生一次行交换,此时行内的相对顺序是不变的,只是每一列元素的相对位置会发生改变,但是发生改变的仅仅是列内元素的相对位置,原本处于同一列的元素依然会处于同一列。
再假设此时发生一次列交换,此时列内的相对顺序是不变的,只是每一行元素的相对位置会发生改变,但是发生改变的仅仅只是行内元素的相对位置,原本处于同一行的元素依然会处于同一行。
基于上述结论,我们只需要判断出矩阵
在编码实现上,有个问题就是若直接开一个2e5 * 2e5的矩阵,复杂度必然是不可接受的。
观察题目,已知
下图是将
观察上图,易知原二维矩阵中,处于同一列的元素,在一维数组中是偏移了长度为
因此,若想在一维数组中遍历二维矩阵的每一行,可以用如下代码:
for (int i = 0; i < n; ++ i) {//共n行 for (int j = 0; j < m; ++ j) {//共m列 //i * m + j } }
若想在一维数组中遍历二维矩阵的每一列,可以用如下代码:
for (int i = 0; i < m; ++ i) {//共m列 for (int j = 0; j < n; ++ j) {//共n行 //j * m + i } }
参考代码
#include<bits/stdc++.h> #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); using namespace std; constexpr int N = 2e5 + 7; int T, n, m; int a[N], b[N], row[N], col[N]; void solve() { cin >> n >> m; for (int i = 0; i < n * m; ++ i) { cin >> a[i]; row[a[i]] = i / m; col[a[i]] = i % m; } for (int i = 0; i < n * m; ++ i) cin >> b[i]; if (n == 1 || m == 1) {//行或列等于1时必相等 cout << "YES\n"; return ; } //求同行 for (int i = 0; i < n; ++ i) { int r = row[b[i * m]]; for (int j = 1; j < m; ++ j) { if (row[b[i * m + j]] != r) { cout << "NO\n"; return ; } } } //求同列 for (int i = 0; i < m; ++ i) { int c = col[b[i]]; for (int j = 1; j < n; ++ j) { if (col[b[j * m + i]] != c) { cout << "NO\n"; return ; } } } cout << "YES\n"; } int main() { IOS cin >> T; while (T --) { solve(); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 【.NET】调用本地 Deepseek 模型