题解:CF1458C Latin Square

题意:给出一个矩阵,满足每行每列都是排列,现在有 6 种操作:

  1. \(\forall i\),令第 \(i\) 行到第 \((i+1)\mod n\) 行。
  2. \(\forall i\),令第 \(i\) 行到第 \((i-1)\mod n\) 行。
  3. \(\forall i\),令第 \(i\) 列到第 \((i+1)\mod n\) 列。
  4. \(\forall i\),令第 \(i\) 列到第 \((i-1)\mod n\) 列。
  5. \(\forall i\),令第 \(i\) 行变成其逆排列。
  6. \(\forall i\),令第 \(i\) 列变成其逆排列。

做法:

首先前四个操作非常简单,我们考虑记录变化量 \((x,y)\),表示原本 \((i,j)\) 变到 \(((i+x)\mod n,(j+y)\mod m)\),但是后面两个操作非常困难,逆排列这个东西不是很好描述。

这里有一个比较特别的 trick,我们直接考虑把值 \(v\) 也计入变化量中,当要求行变成逆排列时,等同于我们令变化量 \((x,y,v)\) 变成 \((x, v, y)\),列类似,最后直接根据这个变化量数组进行变化即可。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e3 + 5, mod = 1e9 + 7;
int v[3], p[3], n, m, a[maxn][maxn][3], b[maxn][maxn];
void solve() {
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> a[i][j][2], a[i][j][2]--, a[i][j][0] = i, a[i][j][1] = j;
	for (int i = 0; i <= 2; i++)
		v[i] = 0, p[i] = i;
	while(m--) {
		char c; cin >> c;
		if(c == 'L')
			v[1]--;
		if(c == 'R')
			v[1]++;
		if(c == 'U')
			v[0]--;
		if(c == 'D')
			v[0]++;
		if(c == 'I')
			swap(v[1], v[2]), swap(p[1], p[2]);
		if(c == 'C')
			swap(v[0], v[2]), swap(p[0], p[2]);
	}
	for (int i = 0; i <= 2; i++)
		v[i] = (v[i] % n + n) % n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			int val[3];
			for (int t = 0; t <= 2; t++)
				val[t] = (a[i][j][p[t]] + v[t]) % n;
			b[val[0]][val[1]] = val[2];
		}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) 	
			cout << b[i][j] + 1 << (j == n - 1 ? '\n' : ' ');
}
signed main() {
	int T;
	cin >> T;
	while(T--)
		solve();
	return 0;
}
posted @ 2025-07-30 13:31  LUlululu1616  阅读(12)  评论(0)    收藏  举报