题目大意:
给出一个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 }
我还在坚持,我还未达到我所想,梦~~一直在