Pixel Shufflent
Description
在一个
n×n
(
n
为偶数) 的黑白位图上反复执行同一个像素混和序列,问重复做几次后会得到原图像?
每个混合序列是由若干个混合命令组成,这些命令如下。
- id:不变
- rot:逆时针旋转 90°
- sym:水平翻转
- bhsym:下一半的图像水平翻转
- bvsym:下一半图像垂直翻转
- div:第
0,2,4,…n−2 行变成第 0,1,2,…,n/2−1 行,第 1,3,5,…,n−1 行变成第 n/2,n/2+1,…n−1 行- mix:行混合。
新图像的第 2k 行依次是原图像的(2k,0),(2k+1,0),(2k,1),(2k+1,1),…,(2k,n2−1),(2k+1,n2−1)这些像素。
第 2k+1 行依次是原图像的(2k,n2),(2k+1,n2),(2k,n2+1),(2k+1,n2+1),…,(2k,n−1),(2k+1,n−1) 对字母 A 使用这
7 种混合法后的效果如图所示。
Input
第一行为位图边长 n (
2≤n≤210) ,第二行为不超过 k (k≤32 )个混合命令。
如果一个命令后面有一个减号“-”,表示应该执行该命令的逆。
命令从右往左执行。
Output
输出最小重复次数。
Sample Input 1
256
rot- div rot div
Sample Output 1
8
Sample Input 2
256
bvsym div mix
Sample Output 2
63457
Solution
每一个操作可视为一个置换,将这些置换的成绩循环分解,然后答案就为所有循环的元素个数的最小公倍数。
Code
#include <iostream> #include <cstdio> #include <cstring> #define PLA(x,y) PLAS[(x)][(y)] using namespace std; char input[100000]; int T,n,cnt; int row[100000]; int to[1300000]; bool vis[1300000]; int PLAS[2000][2000]; int nxt[1300000]; int gcd(int x,int y){ return y==0?x:gcd(y,x%y); } void work(int x){ switch(x){ case 9: for(int i=0;i<n;i++) for(int j=0;j<n;j++) nxt[PLA(i,j)]=to[PLA(j,n-i-1)]; break; case 3: for(int i=0;i<n;i++) for(int j=0;j<n;j++) nxt[PLA(i,j)]=to[PLA(i,n-j-1)]; break; case 4: for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(i>=n/2)nxt[PLA(i,j)]=to[PLA(i,n-j-1)]; break; case 5: for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(i>=n/2)nxt[PLA(i,j)]=to[PLA(n/2+n-1-i,j)]; break; case 7: for(int i=0;i<n;i++) for(int j=0;j<n;j++){ if(!((i)&1))nxt[PLA(i,j)]=to[PLA(i+((j)&1),(j)/2)]; else nxt[PLA(i,j)]=to[PLA(i+((j)&1)-1,(j)/2+n/2)]; } break; case 2: for(int i=0;i<n;i++) for(int j=0;j<n;j++) nxt[PLA(i,j)]=to[PLA(n-j-1,i)]; break; case 6: for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(i<n/2)nxt[PLA(i,j)]=to[PLA((i)*2,j)]; else nxt[PLA(i,j)]=to[PLA(2*(i-n/2)+1,j)]; break; case 13: for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(!((i)&1))nxt[PLA(i,j)]=to[PLA(i/2,j)]; else nxt[PLA(i,j)]=to[PLA(i/2+n/2,j)]; break; case 14: for(int i=0;i<n;i++) for(int j=0;j<n;j++){ if(j<n/2){ if(!((i)&1))nxt[PLA(i,j)]=to[PLA(i,(j)*2)]; else nxt[PLA(i,j)]=to[PLA(i-1,(j)*2+1)]; } else{ if(!((i)&1))nxt[PLA(i,j)]=to[PLA(i+1,(j-n/2)*2)]; else nxt[PLA(i,j)]=to[PLA(i,(j-n/2)*2+1)]; } } break; default:break; } for(int i=0;i<n;i++) for(int j=0;j<n;j++) to[PLA(i,j)]=nxt[PLA(i,j)]; } int main(){ scanf("%d",&n);gets(input);if((input[0]<'a'||input[0]>'z')&&(input[0]<'A'||input[0]>'Z'))gets(input); for(int i=0;i<n;i++) for(int j=0;j<n;j++)PLAS[i][j]=((i)*n+(j)+1); int l=strlen(input);cnt=0; int end=PLA(n-1,n-1); for(int i=1;i<=end;i++)to[i]=nxt[i]=i; for(int i=0;i<=l;i++){ if(input[i]==' '||i==l){ switch(input[i-1]){ case 'd':continue; case 't':row[++cnt]=2;break; case 'v':row[++cnt]=6;break; case 'x':row[++cnt]=7;break; case 'm': if(i>3&&input[i-4]=='h')row[++cnt]=4; else if(i>3&&input[i-4]=='v')row[++cnt]=5; else row[++cnt]=3; break; case '-': switch(input[i-2]){ case 'd':continue; case 't':row[++cnt]=9;break; case 'v':row[++cnt]=13;break; case 'x':row[++cnt]=14;break; case 'm': if(i>4&&input[i-5]=='h')row[++cnt]=4; else if(i>4&&input[i-5]=='v')row[++cnt]=5; else row[++cnt]=3; break; default:break; } break; default:break; } } } for(int i=cnt;i>=1;i--)work(row[i]); int ans=1; for(int i=1;i<=end;i++)if(!vis[i]){ int j=i,tot=0; do{ vis[j]=true; tot++; j=to[j]; }while(i!=j); ans=ans/gcd(ans,tot)*tot; } printf("%d",ans); return 0; }
- mix:行混合。