有一个n*n的图像和7种置换,以及一个置换序列,求将这个序列重复做几次能得到原图像。
将这些置换序列乘起来可得到一个最终置换,这个置换所有循环节的长度的lcm即为答案。
注意置换是从右往左进行的,开始没仔细读题,debug到崩溃~~
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned long long ll; 4 const int N=1024+10; 5 typedef vector<int> Per; 6 Per operator*(const Per& a,const Per& b) { 7 Per c(a.size()); 8 for(int i=0; i<c.size(); ++i)c[i]=b[a[i]]; 9 return c; 10 } 11 Per inv(const Per& a) { 12 Per c(a.size()); 13 for(int i=0; i<c.size(); ++i)c[a[i]]=i; 14 return c; 15 } 16 Per a[10][2]; 17 int n,k,ka; 18 int f(int i,int j) {return i*n+j;} 19 string line; 20 int vis[N*N]; 21 ll lcm(ll a,ll b) {return a/__gcd(a,b)*b;} 22 int main() { 23 int T; 24 for(scanf("%d",&T); T--;) { 25 !ka?++ka:puts(""); 26 scanf("%d ",&n); 27 for(int i=0; i<7; ++i)a[i][0].resize(n*n); 28 for(int i=0; i<n; ++i) 29 for(int j=0; j<n; ++j) { 30 a[0][0][f(i,j)]=f(i,j); 31 a[1][0][f(i,j)]=f(n-1-j,i); 32 a[2][0][f(i,j)]=f(i,n-1-j); 33 a[3][0][f(i,j)]=i<n/2?f(i,j):f(i,n-1-j); 34 a[4][0][f(i,j)]=i<n/2?f(i,j):f(n-1-i+n/2,j); 35 a[5][0][f(i,j)]=i&1?f(i/2+n/2,j):f(i/2,j); 36 a[6][0][f(i,j)]=i&1?f(i-(j&1^1),j/2+n/2):f(i+(j&1),j/2); 37 } 38 for(int i=0; i<7; ++i)a[i][1]=inv(a[i][0]); 39 swap(a[6][0],a[6][1]); 40 Per p=a[0][0]; 41 getline(cin,line); 42 stringstream ss(line); 43 string s; 44 while(ss>>s) { 45 int t=0; 46 if(s.back()=='-')t=1,s.pop_back(); 47 if(s=="id")p=a[0][t]*p; 48 else if(s=="rot")p=a[1][t]*p; 49 else if(s=="sym")p=a[2][t]*p; 50 else if(s=="bhsym")p=a[3][t]*p; 51 else if(s=="bvsym")p=a[4][t]*p; 52 else if(s=="div")p=a[5][t]*p; 53 else if(s=="mix")p=a[6][t]*p; 54 } 55 memset(vis,0,sizeof vis); 56 ll ans=1; 57 for(int i=0; i<p.size(); ++i)if(!vis[i]) { 58 ll cnt=1; 59 vis[i]=1; 60 for(int j=p[i]; j!=i; vis[j]=1,j=p[j])++cnt; 61 ans=lcm(ans,cnt); 62 } 63 printf("%lld\n",ans); 64 } 65 return 0; 66 }