Description
Shuffling the pixels in a bitmap image sometimes yields random looking images. However, by repeating the shuffling enough times, one finally recovers the original images. This should be no surprise, since ``shuffling" means applying a one-to-one mapping
(or permutation) over the cells of the image, which come in finite number.
Problem
Your program should read a number n , and a series of elementary transformations that define a ``shuffling"
of
nxn images. Then, your program should compute the minimal number
m(m > 0) , such that
m applications of always yield the original
nxn image.
For instance if is counter-clockwise 90
o rotation then m = 4 .
Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.
Input is made of two lines, the first line is number n (
2n210
, n even). The number n is the size of images, one image is represented internally by a
nxn pixel matrix
(aji) , where i is the row number and
j is the column number. The pixel at the upper left corner is at row 0 and column 0.
The second line is a non-empty list of at most 32 words, separated by spaces. Valid words are the keywords
id, rot,
sym, bhsym, bvsym,
div and mix, or a keyword followed by ``-". Each keyword key designates an elementary transform (as defined by Figure 1), and
key- designates the inverse of transform
key. For instance, rot- is the inverse of counter-clockwise 90o rotation, that is clockwise 90
o rotation. Finally, the list
k1, k2,..., kp designates the compound transform
=
k1ok2o ... okp . For instance, ``
bvsym rot-" is the transform that first performs clockwise 90
o rotation and then vertical symmetry on the lower half of the image.
Figure 1: Transformations of image (aji) into image
(bji)
Output
For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.
Your program should output a single line whose contents is the minimal number
m(m > 0) such that
is the identity. You may assume that, for all test input, you have
m < 231 .
Sample Input
2 256 rot- div rot div 256 bvsym div mix
Sample Output
8 63457 题意:给你n*n的矩阵和几种操作,问重复几次后会得到原图 思路:每个命令都是一个置换,操作序列就是置换的乘积,我们可以最终的处理出这个矩阵,一个结论:对于一个长度为l的循环A,当且仅当m是l的整数倍的时候A^m才是全等置换,所以答案是多个循环的最小 公倍数#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1100; int n, g[maxn][maxn], vis[maxn][maxn], save[maxn][maxn]; char str[maxn], tmp[maxn]; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } int lcm(int a, int b) { return a / gcd(a, b) * b; } void id() { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) g[i][j] = save[i][j]; } void rot(int flag) { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) { if (flag) save[i][j] = g[n-j-1][i]; else save[n-j-1][i] = g[i][j]; } id(); } void sym(int flag) { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) save[i][j] = g[i][n-1-j]; id(); } void bhsym(int flag) { for (int i = 0; i < n/2; i++) for (int j = 0; j < n; j++) save[i][j] = g[i][j]; for (int i = n/2; i < n; i++) for (int j = 0; j < n; j++) save[i][j] = g[i][n-1-j]; id(); } void bvsym(int flag) { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) { if (i < n / 2) save[i][j] = g[i][j]; else save[i][j] = g[3 * n / 2 - 1 - i][j]; } id(); } void div(int flag) { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) { if (flag == 1) { if (i & 1) save[i / 2 + n / 2][j] = g[i][j]; else save[i / 2][j] = g[i][j]; } else { if (i & 1) save[i][j] = g[i / 2 + n / 2][j]; else save[i][j] = g[i / 2][j]; } } id(); } void mix(int flag) { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) { if ((i & 1) == 0) { if (flag) { if ((j & 1) == 0) save[i][j] = g[i][j / 2]; else save[i][j] = g[i + 1][j / 2]; } else { if ((j & 1) == 0) save[i][j / 2] = g[i][j]; else save[i + 1][j / 2] = g[i][j]; } } else { if (flag) { if ((j & 1) == 0) save[i][j] = g[i - 1][n / 2 + j / 2]; else save[i][j] = g[i][n / 2 + j / 2]; } else { if ((j & 1) == 0) save[i - 1][n / 2 + j / 2] = g[i][j]; else save[i][n / 2 + j / 2] = g[i][j]; } } } id(); } void change(char *str) { int len = strlen(str); int flag = 1; if (str[0] == '-') { flag = 0; str++; } if (strcmp(str, "tor") == 0) rot(flag); else if (strcmp(str, "mys") == 0) sym(flag); else if (strcmp(str, "myshb") == 0) bhsym(flag); else if (strcmp(str, "mysvb") == 0) bvsym(flag); else if (strcmp(str, "vid") == 0) div(flag); else if (strcmp(str, "xim") == 0) mix(flag); } void tra() { int len = strlen(str); int sn = 0; for (int i = len - 1; i >= 0; i--) { if (str[i] == ' ') { tmp[sn] = '\0'; change(tmp); sn = 0; } else { tmp[sn++] = str[i]; } } tmp[sn] = '\0'; change(tmp); } int solve() { int ans = 1; memset(vis, 0, sizeof(vis)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (!vis[i][j]) { vis[i][j] = 1; int cnt = 1; int x = g[i][j] / n; int y = g[i][j] % n; while (!vis[x][y]) { cnt++; vis[x][y] = 1; int t = g[x][y] / n; y = g[x][y] % n; x = t; } ans = lcm(ans, cnt); } } } return ans; } void init() { scanf("%d", &n); getchar(); gets(str); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { g[i][j] = i * n + j; } } } int main() { int t; scanf("%d", &t); while (t--) { init(); tra(); printf("%d\n", solve()); if (t) printf("\n"); } return 0; }