poj1026Cipher(置换群)
找循环节 然后所有子循环节的最小公倍数就是总的循环节 找结果的时候也按一个个置换来进行转换 不然也TLE
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 #include<stdlib.h> 7 #include<map> 8 using namespace std; 9 #define LL long long 10 int p[210]; 11 char s[210]; 12 char ss[210],sq[210]; 13 int vis[210]; 14 int qu[210][210]; 15 int po[210]; 16 int num[210]; 17 LL gcd(int a,int b) 18 { 19 return b==0?a:gcd(b,a%b); 20 } 21 int main() 22 { 23 int i,j,n; 24 LL k; 25 while(scanf("%d",&n)&&n) 26 { 27 memset(vis,0,sizeof(vis)); 28 memset(num,0,sizeof(num)); 29 for(i = 1; i <= n ; i++) 30 { 31 scanf("%d",&p[i]); 32 po[p[i]] = i; 33 } 34 LL sk = 1;int g=0; 35 for(i =1; i <= n ;i++) 36 { 37 if(!vis[i]) 38 { 39 vis[i] = 1; 40 g++; 41 int x = i,o=1; 42 qu[g][o] = i; 43 while(1) 44 { 45 x = p[x]; 46 if(!vis[x]) 47 { 48 vis[x] = 1; 49 } 50 else 51 break; 52 o++; 53 qu[g][o] = x; 54 } 55 num[g] = o; 56 sk = sk/gcd(sk,o)*o; 57 } 58 } 59 while(scanf("%lld%*c",&k)&&k) 60 { 61 gets(s); 62 int kk = strlen(s); 63 for(i = kk ; i < n ; i++) 64 s[i] = ' '; 65 s[n] = '\0'; 66 strcpy(ss,s); 67 strcpy(sq,s); 68 k = k%sk; 69 for(i =1 ; i <= g ; i++) 70 { 71 int kk = k%num[i]; 72 strcpy(ss,sq); 73 while(kk) 74 { 75 for(j = 1 ; j <= num[i] ; j++) 76 s[qu[i][j]-1] = ss[po[qu[i][j]]-1]; 77 strcpy(ss,s); 78 kk--; 79 } 80 } 81 puts(s); 82 } 83 puts(""); 84 } 85 return 0; 86 }