思路:

  • 代数法分析
    • 对于每一种变化,我们可以用代数的方法将其表示出来
      • 第一种变化:a[i][j] --> a[n - i + 1][n - j + 1]
      • 第二种变化:a[i][j] --> a[n - i + 1][j]
    • 最有意思的在于我们如果尝试对翻转的再翻转或者镜像的再镜像,其 i,j 的位置是会复原的(废话)
      • 于是我们知道 x --> n - x + 1 这个变化是自反的(通过两次这样的变化其值又会变回 x )
  • 所以最后的解法:考虑使得 i,j 变成 n - x + 1 形式的操作次数,若发生偶数次则当作无事发生,否则就进行相对应的变换。
#include <iostream>

using namespace std;

int a[1009][1009], n, q;

int main() {
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= n; j ++)
            scanf("%d", a[i] + j);
    }
    cin >> q;
    int sum1 = 0;
    for(int i = 0; i < q; i ++) {
        int x; cin >> x;
        if(x == 1) sum1 ++;
        else sum2 ++;
    }
    if(q & 1) {  /// 四种情况
        if(sum1 & 1) {
            for(int i = n; i; i --) {
                for(int j = n; j; j --) {
                    printf("%d ", a[i][j]);
                }   cout << endl;
            }
        } else {
            for(int i = n; i; i --) {
                for(int j = 1; j <= n; j ++)
                    printf("%d ", a[i][j]);
                cout << endl;
            }
        }
    } else {
        if(sum1 & 1) {
            for(int i = 1; i <= n; i ++) {
                for(int j = n; j; j --)
                    printf("%d ", a[i][j]);
                cout << endl;
            }
        } else {
            for(int i = 1; i <= n; i ++) {
                for(int j = 1; j <= n; j ++)
                    printf("%d ", a[i][j]);
                cout << endl;
            }
        }
    }
    return 0;
}