题解:CF1458C Latin Square
题意:给出一个矩阵,满足每行每列都是排列,现在有 6 种操作:
- \(\forall i\),令第 \(i\) 行到第 \((i+1)\mod n\) 行。
- \(\forall i\),令第 \(i\) 行到第 \((i-1)\mod n\) 行。
- \(\forall i\),令第 \(i\) 列到第 \((i+1)\mod n\) 列。
- \(\forall i\),令第 \(i\) 列到第 \((i-1)\mod n\) 列。
- \(\forall i\),令第 \(i\) 行变成其逆排列。
- \(\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;
}

浙公网安备 33010602011771号