题目大意:

给出一个A~Z的置换G,问能否找到一个A~Z的置换G' 能够用来表示为 G = G'*G'

 

由定理:

任意一个长为 L 的置换的k次幂,都会把自己的每一个循环节分裂成gcd(L, K)份,并且每一份的长度都为L/gcd(L,K)

 

这里是置换的平方,所以G'长度为偶数的循环节必然会分裂为两个相等的循环节,长度为奇数的循环节还是一个循环节长度不变

 

那么得到的G中长度为偶数的循环节必然是由G'中偶数的循环节分裂得到,奇数的循环节可以不多做考虑,就认为它是原来的奇数循环节保持不变所得

所以这里只要判断G中数量为偶数的循环节能否做到两两配对即可

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 int cnt[30] , to[30] , vis[30];
 7 char str[30];
 8 
 9 void solve(int u)
10 {
11     int ans = 1 , v = u;
12     while(u != to[v]){
13         vis[v] = 1;
14         ans++;
15         v = to[v];
16     }
17     vis[v] = 1;
18     cnt[ans]++;
19 }
20 
21 int main()
22 {
23    // freopen("a.in" , "r" , stdin);
24     int T;
25     scanf("%d" , &T);
26     while(T--)
27     {
28         scanf("%s",  str);
29         //建立映射关系
30         for(int i=0 ; i<26 ; i++){
31             to[i+1] = str[i]-'A'+1;
32         }
33         memset(cnt , 0 , sizeof(cnt));
34         memset(vis , 0 , sizeof(vis));
35         for(int i=1 ; i<=26 ; i++){
36             if(!vis[i]) solve(i);
37         }
38         int flag = 1;
39         //遇到任何一个循环节为偶数的不能配对的情况就会输出No
40         for(int i=1 ; i<=26 ; i++){
41             if(cnt[i] && !(i&1)){
42                 if(cnt[i]&1){
43                     flag = 0;
44                     break;
45                 }
46 
47             }
48         }
49         if(flag) printf("Yes\n");
50         else printf("No\n");
51     }
52     return 0;
53 }

 

 posted on 2015-01-22 12:15  Love风吟  阅读(255)  评论(0编辑  收藏  举报