一个矩阵,每行、每列都是个排列(置换)。
支持以下操作:总体上下左右位移,每行或列分别取逆置换。
输出一堆操作之后的矩阵。
\(n\le 1000,m\le 10^5\)
一直在想抽象代数,于是一直没有切。
正解比较简单:可以把原矩阵映射到三维空间中:\((i,j,a_{i,j})\)。取逆置换相当于将两维交换。
于是维护下\((0,0,0)\)经过一系列操作之后变成什么,并且维护最后矩阵中的每一维在一开始是哪一维,于是就可以求出对于任意点\((x,y,z)\)在操作之后移到了哪里。
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1005
int n,m;
int a[N][N],b[N][N];
struct vec{
int x[3];
void clear(){x[0]=x[1]=x[2]=0;}
int &operator[](int i){return x[i];}
} o;
int r[3];
char op[100005];
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int T;
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&m);
for (int i=0;i<n;++i)
for (int j=0;j<n;++j)
scanf("%d",&a[i][j]),a[i][j]--;
o.clear();
for (int i=0;i<3;++i)
r[i]=i;
scanf("%s",op);
for (int i=0;i<m;++i){
if (op[i]=='R')
o[1]=(o[1]+1)%n;
else if (op[i]=='L')
o[1]=(o[1]-1+n)%n;
else if (op[i]=='D')
o[0]=(o[0]+1)%n;
else if (op[i]=='U')
o[0]=(o[0]-1+n)%n;
else if (op[i]=='I')
swap(o[1],o[2]),swap(r[1],r[2]);
else
swap(o[0],o[2]),swap(r[0],r[2]);
}
for (int i=0;i<n;++i)
for (int j=0;j<n;++j){
vec v={i,j,a[i][j]},u;
for (int i=0;i<3;++i)
u[i]=(o[i]+v[r[i]])%n;
b[u[0]][u[1]]=u[2];
// printf("(%d,%d,%d)\n",u[0],u[1],u[2]);
}
for (int i=0;i<n;++i,printf("\n"))
for (int j=0;j<n;++j)
printf("%d ",b[i][j]+1);
printf("\n");
}
return 0;
}