题目大意。首先输入长度为n的数字串,长度少于n,不足用空格补全,设为key[i],表示第i个字符置换一次后跑到key[i]的位置。然后输入若干字符序列,设字符序列为Src(若长度不足n则后面用空格补齐),求Src中的每个字符进行m次置换后的字符序列Dst。
不懂的可以先看看群论的知识:近世代数上有写。。。
对于置换群对于给定的置换规则在第k次置换后有一个循环节ni,求出每个位置的循环节后
对于m次变换后 相当于只是变换了 m%n次大大节约运算那么也就只用多算m%ni次的结果就可以了
代码如下:
#include
#include
#include
#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;
}