题意:
一个长度为26的字符串,包含26个字母,问这个置换能否是其他某个置换的平方。
题解:
首先引入定理:
1.任意一个长为 L 的置换的k次幂,会把自己分裂成gcd(L,k) 分, 并且每一份的长度都为 L / gcd(l,k)
2.假如 d = gcd(L,K),l = L / gcd(L,k),那么我们只需要找到d个长为l的循环,将他们交错循环连接成一个长为 d * l 的大循环, 这样一个过程就相当于开k次方。
如果一个置换平方后,长度为奇数的循环节任然是奇数,长度为偶数的循环节会分解成两个长度为偶数的循环节,那么这个置换要是另外一个置换的平方,这个置换中偶数循环节要能一一配对,那么偶数循环节的个数肯定是偶数个。
解决这个问题:偶数循环节的个数是否是偶数个。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> #define B(x) (1<<(x)) using namespace std; typedef long long ll; void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } void cmax(ll& a,ll b){ if(b>a)a=b; } void cmin(ll& a,ll b){ if(b<a)a=b; } void add(int& a,int b,int mod){ a=(a+b)%mod; } void add(ll& a,ll b,ll mod){ a=(a+b)%mod; } const int oo=0x3f3f3f3f; const int MOD=2012; const int maxn=30; char str[maxn]; int a[maxn],vis[maxn]; int cnt[maxn],num; int main(){ //freopen("E:\\read.txt","r",stdin); int T; scanf("%d",&T); while(T--){ scanf("%s",str+1); for(int i=1;i<=26;i++)a[i]=str[i]-'A'+1; memset(vis,0,sizeof vis); memset(cnt,0,sizeof cnt); for(int i=1;i<=26;i++){ if(!vis[i]){ vis[i]=1; num=1; int temp=a[i]; while(!vis[temp]){ num++; vis[temp]=1; temp=a[temp]; } cnt[num]++; } } int f=1; for(int i=2;i<=26;i+=2){ if(cnt[i]%2!=0){ f=0; break; } } if(f) printf("Yes\n"); else printf("No\n"); } return 0; }