CF1458C. Latin Square

一个矩阵,每行、每列都是个排列(置换)。

支持以下操作:总体上下左右位移,每行或列分别取逆置换。

输出一堆操作之后的矩阵。

\(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;
}
上一篇:c++抽象类和纯虚函数


下一篇:20201207大一集训题之y题思维题之数组+素数