思路挺简单的,题目中的每个命令(包括命令的逆)相当于一个置换。
用O(n2k)的时间复杂度从右往左求出这些置换的乘积A,然后求m使Am = I(I为全等置换)
还是先把A分解循环,m则等于所有循环节长度的最小公倍数。
需要注意的是:
执行命令是从右往左执行的,这是题目中说的=_=
其他命令还好,mix那个命令把我搞得晕头转向,题中给的是反的,我们要反过来求原图像(i, j)在新图像中的位置。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <string> 5 #include <sstream> 6 #include <vector> 7 using namespace std; 8 9 int gcd(int a, int b) 10 { return b == 0 ? a : gcd(b, a%b); } 11 12 int lcm(int a, int b) 13 { return a / gcd(a, b) * b; } 14 15 const int maxn = 1025; 16 int n; 17 char s[300], op[35][10]; 18 19 inline int ID(int i, int j) 20 { return i*n + j; } 21 22 int newpos(int i, int j, const char* op) 23 { 24 if(op[0] == 'r') return ID(n-j-1, i); 25 if(op[0] == 's') return ID(i, n-j-1); 26 if(op[0] == 'b' && op[1] == 'h') 27 { 28 if(i >= n/2) return ID(i, n-j-1); 29 return ID(i, j); 30 } 31 if(op[0] == 'b' && op[1] == 'v') 32 { 33 if(i >= n/2) return ID(n-(i-n/2)-1, j); 34 return ID(i, j); 35 } 36 if(op[0] == 'd') 37 { 38 if(i & 1) return ID(n/2 + i/2 ,j); 39 return ID(i/2, j); 40 } 41 if(op[0] == 'm') 42 { 43 int k = i/2; 44 if(j < n/2) return i % 2 == 0 ? ID(k*2, j*2) : ID(k*2, j*2+1); 45 else return i % 2 == 0 ? ID(2*k+1, 2*(j-n/2)) : ID(2*k+1, 2*(j-n/2)+1); 46 } 47 return ID(i, j); 48 } 49 50 int cur[maxn * maxn], origin[maxn * maxn]; 51 52 void apply(const char* op) 53 { 54 for(int i = 0; i < n*n; i++) origin[i] = cur[i]; 55 bool inv = op[strlen(op)-1] == '-' ? true : false; 56 for(int i = 0; i < n; i++) 57 for(int j = 0; j < n; j++) 58 { 59 int p = ID(i, j), p2 = newpos(i, j, op); 60 if(inv) cur[p] = origin[p2]; 61 else cur[p2] = origin[p]; 62 } 63 } 64 65 bool vis[maxn * maxn]; 66 67 int solve() 68 { 69 memset(vis, false, sizeof(vis)); 70 int ans = 1; 71 for(int i = 0; i < n*n; i++) if(!vis[i]) 72 { 73 int cnt = 0, j = i; 74 do 75 { 76 vis[j] = 1; 77 cnt++; 78 j = cur[j]; 79 }while(j != i); 80 ans = lcm(cnt, ans); 81 } 82 return ans; 83 } 84 85 int main() 86 { 87 //freopen("in.txt", "r", stdin); 88 89 int T; 90 scanf("%d", &T); 91 for(int kase = 0; kase < T; kase++) 92 { 93 if(kase) puts(""); 94 95 scanf("%d", &n); getchar(); 96 string line, temp; 97 getline(cin, line); 98 stringstream ss(line); 99 vector<string> op; 100 while(ss >> temp) op.push_back(temp); 101 102 for(int i = 0; i < n*n; i++) cur[i] = i; 103 for(int i = op.size() - 1; i >= 0; i--) apply(op[i].c_str()); 104 printf("%d ", solve()); 105 } 106 107 return 0; 108 }