poj 1026

蛋疼了好长时间,还是早上精神好,理解的快一些。

就是求一个序列置换k次后的结果,由于肯定是循环的,我一开始做的是求出每个循环的长度,再求出最小公倍数m,

用k%m,即置换k%m次即为最后的答案,但是无情的TLE了。

后来才想懂,其实每个元素都属于一个小的循环,假设长度为len[i],只需要让这个元素在它所在的小循环里循环k%len[i]次即可

//============================================================================
// Name        : 1026.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;


int n, k;
int m;
int a[220], b[220], len[220];
char s[220], c, ans[220];



void Circle(){
	memset(len, 0, sizeof(len));
	int temp, t, curlen;
	for(int i = 1;i <= n;i++){
		temp = i;
		t = a[i];
		curlen = 1;
		while(t != temp){
			curlen++;
			t = a[t];
		}
		len[i] = curlen;
	}
}



int main() {
	freopen("a.txt", "r", stdin);
	while(scanf("%d", &n)&&n){
		for(int i = 1;i <= n;i++){
			scanf("%d", &a[i]);
		}
		Circle();
		while(scanf("%d", &k)&&k){
			scanf("%c", &c);
			for(int i = 1;i <= n;i++){
				s[i] = ' ';
			}
			for(int i = 1;i <= n;i++){
				scanf("%c", &c);
				if(c == '\n'){
					break;
				}
				s[i] = c;
			}
			for(int i = 1;i <= n;i++){
				b[i] = i;
			}
			for(int i = 1;i <= n;i++){
				for(int j = 1;j <= k%len[i];j++){
					b[i] = a[b[i]];
				}
			}
//			for(int i = 1; i <= n;i++){
//				printf("%d ", b[i]);
//			}
//			printf("\n");
			for(int i = 1;i <= n;i++){
				ans[b[i]] = s[i];
			}
			for(int i = 1;i <= n;i++){
				printf("%c", ans[i]);
			}
			printf("\n");
		}
		printf("\n");
	}
	return 0;
}

  

posted @ 2011-07-24 09:07  KOKO's  阅读(555)  评论(0编辑  收藏  举报