矩阵重塑(其二)
题目复制过来格式有点问题,可以看原题链接↗
刷新
时间限制: 1.0 秒
空间限制: 512 MiB
相关文件: 题目目录(样例文件)
题目背景
矩阵转置操作是将矩阵的行和列交换的过程。在转置过程中,原矩阵 AA 的元素 aijaij* 会移动到转置后的矩阵 ATAT 的 aji*aji 的位置。这意味着 AA 的第 ii 行第 jj 列的元素在 ATAT 中成为了第 jj 行第 ii 列的元素。
例如,有矩阵 AA 如下:
A=[abcdef]A=[adbecf]
它的转置矩阵 ATAT 会是:
AT=[adbecf]AT=*abcde*f
矩阵转置在线性代数中是一个基本操作,广泛应用于各种数学和工程领域。
题目描述
给定 n×mn×m 的矩阵 MM,试编写程序支持以下查询和操作:
- 重塑操作 p*p*、q*q*:将当前矩阵重塑为 p×qp×q 的形状(重塑的具体定义见上一题);
- 转置操作:将当前矩阵转置;
- 元素查询 i*i*、j*j*:查询当前矩阵第 ii 行 jj 列的元素(0≤i<n0≤i<n 且 0≤j<m0≤j<m)。
依次给出 tt 个上述查询或操作,计算其中每个查询的结果。
输入格式
从标准输入读入数据。
输入共 n+t+1n+t+1 行。
输入的第一行包含三个正整数 nn、mm 和 tt。
接下来依次输入初始矩阵 MM 的第 00 到第 n−1n−1 行,每行包含 mm 个整数,按列下标从 00 到 m−1m−1 的顺序依次给出。
接下来输入 tt 行,每行包含形如 op a b
的三个整数,依次给出每个查询或操作。具体输入格式如下:
- 重塑操作:
1 p q
- 转置操作:
2 0 0
- 元素查询:
3 i j
输出格式
输出到标准输出。
每个查询操作输出一行,仅包含一个整数表示查询结果。
样例1输入
3 2 3
1 2
3 4
5 6
3 0 1
1 2 3
3 1 2
样例1输出
2
6
样例2输入
3 2 5
1 2
3 4
5 6
3 1 0
2 0 0
3 1 0
1 3 2
3 1 0
样例2输出
3
2
5
初始矩阵: [123456]135246, (1,0)(1,0) 位置元素为 33;
转置后: [135246][123456], (1,0)(1,0) 位置元素为 22;
重塑后: [135246]154326, (1,0)(1,0) 位置元素为 55。
子任务
8080 的测试数据满足:
- t≤100t≤100;
全部的测试数据满足:
- t≤105t≤105 且其中转置操作的次数不超过 100100;
- nn、mm 和所有重塑操作中的 pp、qq 均为正整数且 n×m=p×q≤104n×m=p×q≤104;
- 输入矩阵中每个元素的绝对值不超过 10001000。
提示
- 对于 n×mn×m 的矩阵,虽然转置和重塑操作都可以将矩阵形态变为 m×nm×n,但这两种操作通常会导致不同的结果。
- 评测环境仅提供各语言的标准库,特别地,不提供任何线性代数库(如
numpy
、pytorch
等)。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int n,m,t;
const int N=1e4+10;
int a[N];
int main(){
cin>>n>>m>>t;
for(int i=0;i<n*m;i++){
cin>>a[i];
}
int m1=m;//记录每次更新后的行值和列值
int n1=n;
while(t--){
int op,p,q;
cin>>op>>p>>q;
if(op==1){
n1=p;
m1=q;
}else if(op==2){
int tmp[N];
for(int i=0,x=0;i<n*m;i++,x++){
tmp[(x%m1)*n1+x/m1]=a[i];//关于此处公式,见代码下方文字
}
for(int i=0;i<n*m;i++){
a[i]=tmp[i];
}
swap(n1,m1);
}else{
cout<<a[p*m1+q]<<endl;//此处!就利用了第一问给的提示,原二维数组转化为一维数组,某个值的坐标从(i,j)变为i*m(当前列数)+j
}
}
return 0;
}
原数组在(i,j)处的值,经过转置变成了(j,i)处的值
而这两个坐标对应到一维数组中即为i*m+j→j*m1+i
令i*m+j=x
,则i=x/m
(为下取整,x/m的值正好为i),j=x%m
故将i和j代入转置后的式子中,一维数组对应该值的坐标为(x%m)*m1+x/m
,得证
tmp[(x%m)*m1+x/m]=a[i]
其中m为原矩阵的列数,m1为转置后矩阵的列数(则为原矩阵行数,所以代码中是(x%m1)*n1+x/m1
)