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 }