poj1026 置换群的基础题 m次变换后的结果

题目大意。首先输入长度为n的数字串,长度少于n,不足用空格补全,设为key[i],表示第i个字符置换一次后跑到key[i]的位置。然后输入若干字符序列,设字符序列为Src(若长度不足n则后面用空格补齐),求Src中的每个字符进行m次置换后的字符序列Dst。

不懂的可以先看看群论的知识:近世代数上有写。。。

对于置换群对于给定的置换规则在第k次置换后有一个循环节ni,求出每个位置的循环节后

对于m次变换后 相当于只是变换了 m%n次大大节约运算那么也就只用多算m%ni次的结果就可以了

代码如下:

#include <stdlib.h>
#include <cstring>
#include <iostream>
#define MAX 202
using namespace std; 
int key[MAX], t[MAX];
 
/* 求解置换周期 */
void get_time(int n)
{
	int i, j, count;
	for (i = 1; i <= n; i++)
	{
		j = key[i];
		count = 1;
		/* 直到轮回 */
		while(i != j)
		{
			count++;
			j = key[j];
		}
		t[i] = count;
	}
}
 
int main()
{
	int i, j, m, n, len;
	char src[MAX], dst[MAX];
 
	while(scanf("%d", &n)!=EOF)
	{
		if (n == 0) break; 
		for (i = 1; i <= n; i++)
		{
			scanf("%d", &key[i]);
		} 
		/* 初始化周期数组 */
		memset(t, 0, sizeof(t)); 
		get_time(n);		
 
		while(scanf("%d", &m)!=EOF)
		{			
			if (m == 0) break;
			getchar(); 
			/* 读入输入串 */
			//这个输入比较麻烦点因为要算入空格,所以用gets 
			gets(src + 1); 
			/* 补全输入串 */
			for (i = strlen(src + 1) + 1; i <= n; i++)
			{
				src[i] = ' ';
			}
			src[n + 1] = '\0'; 
			/* 求解输出串 */
			for (i = 1; i <= n; i++)
			{
				int pos = i;
				//t[i]记录的是循环节,那么m%t[i]就是要变换的次数				 
				for (j = 0; j < m % t[i]; j++)
				{
					pos = key[pos];
				}
				//将第i个位置变换到pos的位置上去 
				dst[pos] = src[i];
			}
			dst[n + 1] = '\0';
 
			puts(dst + 1);
		}
		printf("\n");		
	} 
	return 0;
}


你可能感兴趣的:(poj1026 置换群的基础题 m次变换后的结果)