L e o n a r d o ′ s N o t e b o o k Leonardo's\ Notebook Leonardo′s Notebook
D
e
s
c
r
i
p
t
i
o
n
\mathcal{Description}
Description
原序列为
{
A
,
B
,
C
.
.
.
Y
,
Z
}
\{A,B,C...Y,Z\}
{A,B,C...Y,Z},
请问有没有一种置换
T
T
T, 使得连续置换两次得到给出的序列
{
X
1
,
X
2
.
.
.
X
N
}
\{X_1,X_2...X_N\}
{X1,X2...XN}.
S
o
l
u
t
i
o
n
\mathcal{Solution}
Solution
<置换群快速幂运算研究与探讨>
由这篇文章可以得到以下三个结论:
注意结论中的
T
T
T 是 循环节,
设 符合条件的置换 操作前其中一个循环节为
T
T
T,
在这道题目中 指数
k
k
k 为
2
2
2, 于是操作后
- 若 T T T 的长度为奇数, 说明 g c d ( s i z e , k ) gcd(size,k) gcd(size,k)为 1 1 1, 则 T T T 长度不变, 顺序可能会变, 但仍然是一个循环节.
- 若 T T T 的长度为偶数, 说明 g c d ( s i z e , j ) gcd(size, j) gcd(size,j) 为 2 2 2, 则 T T T 长度减半, 相当于分裂为两个新的循环节.
所以在给出的序列中, 必须满足 长度为偶数且相等的循环节必须两两配对 才可能被 T 2 T^2 T2 置换过来.
C
o
d
e
\mathcal{Code}
Code
#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;
}