LA3641 Leonardo's Notebook

Leonardo's Notebook

 题目大意:26个大写字母置换B,问是否存在一个置换A,使得A^2 = B

 

根据结论:

两个长度为n的相同循环相乘,当n为奇数时结果也是一个长度为n的循环;n为偶数时分裂为两个长度为n/2的循环

反过来,长度为奇数n的循环B,都能找到一个长度为n的循环A使得A^2 = B

对于任意两个长度为n(n不一定为偶数)的不相交循环B和C,都能找到一个长度为2n的循环A使得A^2 = BC

直接求循环判断就好,统计循环大小

重点关注如何而寻找循环

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 #include <queue>
 7 #include <vector>
 8 #include <cmath> 
 9 #define min(a, b) ((a) < (b) ? (a) : (b))
10 #define max(a, b) ((a) > (b) ? (a) : (b))
11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
12 inline void swap(int &a, int &b)
13 {
14     long long tmp = a;a = b;b = tmp;
15 }
16 inline void read(int &x)
17 {
18     x = 0;char ch = getchar(), c = ch;
19     while(ch < '0' || ch > '9') c = ch, ch = getchar();
20     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
21     if(c == '-') x = -x;
22 }
23 
24 const int INF = 0x3f3f3f3f;
25 
26 char s[30];
27 int t, cnt[30], b[30], ok;
28 
29 int main()
30 {
31     read(t);
32     for(;t;--t)
33     {
34         scanf("%s", s);
35         memset(cnt, 0, sizeof(cnt));memset(b, 0, sizeof(b));
36         for(register int i = 0;i < 26;++ i) 
37         {
38             if(!b[i])
39             {
40                 int j = i, tot = 0;
41                 do
42                 {
43                     b[j] = 1;
44                     ++ tot;
45                     j = s[j] - 'A';
46                 }while(j != i);
47                 ++ cnt[tot];
48             }
49         }
50         ok = 1;
51         for(register int i = 2;i <= 26;i += 2) 
52             if(cnt[i] & 1)
53             {
54                 printf("No\n");
55                 ok = 0;
56                 break;
57             } 
58         if(!ok) continue;
59         printf("Yes\n");
60     }
61     return 0;
62 }
LA3641

 

posted @ 2018-01-19 20:30  嘒彼小星  阅读(197)  评论(0编辑  收藏  举报