分析:
参考资料:置换群快速幂运算研究与探讨
这里给出结论:
结论一: 一个长度为
L
L
的循环,
L
L
是的倍数,则
Tk
T
k
是
k
k
个循环的乘积,每个循环分别是循环中下标
i(mod)k=0,1,2…
i
(
m
o
d
)
k
=
0
,
1
,
2
…
的元素按顺序的连接
结论二:一个长度为
L
L
的循环,
gcd(L,k)=1
g
c
d
(
L
,
k
)
=
1
,则
Tk
T
k
是一个循环,与循环
T
T
不一定相同
结论三:一个长度为的循环
T
T
,是
gcd(L,k)
g
c
d
(
L
,
k
)
个循环的乘积,每个循环分别是循环
T
T
中下标的元素的连接
这道题需要用到上述结论的逆:
假设初始置换是
S
S
,我们把分解成若干轮换
Ti
T
i
因为我们只进行两次置换
那么只用考虑轮换的大小的奇偶性(
gcd(X,2)=1/2−−−>mod2
g
c
d
(
X
,
2
)
=
1
/
2
−
−
−
>
m
o
d
2
)
- 假如是一个长度为奇数的轮换 T T ,是不会发生分裂的,得到的还是一个长度为奇数的轮换
- 假如是一个长度为偶数的轮换
T
T
,是会分裂成两个长度相等的轮换
- 得到两个长度为偶数的轮换
- 得到两个长度为奇数的轮换
仔细观察一下,在最后得到的所有轮换中,偶数长度的轮换一定是成对存在的
即如果当前是轮换的大小为偶数,那么ta一定是由某个轮换分裂成的,一定是成对出现的
我们就可以利用这个性质,如果得到的置换中大小为偶数
X
X
的轮换个数为
cntX(mod)2==0−−−>Yes
c
n
t
X
(
m
o
d
)
2
==
0
−
−
−
>
Y
e
s
:成对存在
cntX(mod)2==1−−−>No
c
n
t
X
(
m
o
d
)
2
==
1
−
−
−
>
N
o
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,a[30],belong[30],cnt[30];
char s[30];
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%s",s+1);
for (int i=1;i<=26;i++) a[i]=s[i]-'A'+1;
memset(belong,0,sizeof(belong));
memset(cnt,0,sizeof(cnt));
int tot=0;
for (int i=1;i<=26;i++) if (!belong[i])
{
tot++;
int x=i,l=0;
do {
belong[x]=1; l++; x=a[x];
} while(x!=i);
cnt[l]++;
}
bool ff=1;
for (int i=1;i<=26;i++) if (i%2==0&&cnt[i]%2==1) {ff=0;break;}
if (ff) printf("Yes\n");
else printf("No\n");
}
return 0;
}