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; }