POJ 3128 Leonardo's Notebook[置换群幂相关]
原序列为 ,
请问有没有一种置换 , 使得连续置换两次得到给出的序列 .
由这篇文章可以得到以下三个结论:
注意结论中的 是 循环节,
设 符合条件的置换 操作前其中一个循环节为 ,
在这道题目中 指数 为 , 于是操作后
- 若 的长度为奇数, 说明 为 , 则 长度不变, 顺序可能会变, 但仍然是一个循环节.
- 若 的长度为偶数, 说明 为 , 则 长度减半, 相当于分裂为两个新的循环节.
所以在给出的序列中, 必须满足 长度为偶数且相等的循环节必须两两配对 才可能被 置换过来.
#include<cstdio>
#include<cstring>
#define reg register
int A[30];
int sum[30];
char S[30];
bool Used[30];
void Work(){
scanf("%s", S+1);
for(reg int i = 1; i <= 26; i ++) A[i] = S[i]-'A'+1;
memset(Used, 0, sizeof Used);
memset(sum, 0, sizeof sum);
for(reg int i = 1; i <= 26; i ++)
if(!Used[A[i]]){
int to = A[i], len = 0;
while(!Used[to]) Used[to] = 1, len ++, to = A[to];
sum[len] ++;
}
for(reg int i = 1; i <= 13; i ++)
if(sum[i<<1] & 1){ printf("No\n"); return ; }
printf("Yes\n");
}
int main(){
int T;
scanf("%d", &T);
while(T --) Work();
return 0;
}