poj 3128 Leonardo's Notebook(置换的幂)

Posted cutemush

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 3128 Leonardo's Notebook(置换的幂)相关的知识,希望对你有一定的参考价值。

http://poj.org/problem?id=3128

 大致题意:输入一串含26个大写字母的字符串,可以把它看做一个置换,判断这个置换是否是某个置换的平方

可以先正着考虑一个置换的平方出现什么情况。对于置换中的循环,若其长度为偶数Len,平方以后一定分成了两个长度相等,值为Len/2,其值可奇可偶的循环,若长度是奇数,平方以后仍是一个循环,长度不变。因此,考虑当前置换,若某个循环的长度为偶数,那么它一定是原始置换平方得来的,而且等长度的循环一定是成对成对出现。对于长度为奇数的循环,它可能是原始置换某个长度为偶数的循环平方得到的,也可能是长度为奇数的循环平方得来的。所以,判定当前置换是否是某个置换的平方等价于判断当前置换长度为偶数的循环个数是否为偶数个。

原文链接:https://blog.csdn.net/u013081425/article/details/31417679

 

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#define LL long long
#define _LL __int64
#define eps 1e-8
#define PI acos(-1.0)
using namespace std;
 
const int maxn = 1010;
const int INF = 0x3f3f3f3f;
 
int a[30];
char s[30];
int vis[30];
int num[30];
 
bool solve()
{
	memset(vis,0,sizeof(vis));
	memset(num,0,sizeof(num));
	int i;
 
	while(1)
	{
		for(i = 1; i <= 26; i++)
			if(!vis[a[i]])
				break;
		if(i > 26)
			break;
		int cnt = 1;
		vis[i] = 1;  //不要忘记标记i
		int t = a[i];
		vis[t] = 1;
		while(t != i)
		{
			vis[t] = 1;
			t = a[t];
			cnt++;
		}
		if(cnt % 2 == 0) //是偶数,对应循环个数就加1
			num[cnt]++;
	}
	int flag = 1;
	for(int i = 2; i <= 26; i += 2)
	{
		if(num[i] % 2 != 0)
		{
			flag = 0;
			break;
		}
	}
	if(flag == 1)
		return true;
	return false;
}
int main()
{
	int test;
	scanf("%d",&test);
	while(test--)
	{
		scanf("%s",s+1);
		for(int i = 1; i <= 26; i++)
			a[i] = s[i]-‘A‘ + 1;
		if(solve())
			printf("Yes
");
		else printf("No
");
	}
	return 0;
}

  

 

以上是关于poj 3128 Leonardo's Notebook(置换的幂)的主要内容,如果未能解决你的问题,请参考以下文章

poj 3128 Leonardo's Notebook(置换的幂)

poj 3128 Leonardo's Notebook (置换群的整幂运算)

poj 3128 关于置换群的规律

LA3641 Leonardo's Notebook

Leonardo's Notebook UVALive - 3641(置换)

LA 3641 Leonardo's Notebook (置换群)