题目链接
题意
题意:有个字符串,按照给定的指环规则进行置换,也就是num[i]和第i个进行指环,求置换后的字符串
思路:找出循环节,所谓的循环结就是,这N个数字进行循环,那么循环N次后,这N个数字肯定还是和第一次是一样的。
第一种做法:预处理每位i 进行j 次到达位置,b[i][j]
第二种做法:处理出所有的循环节,然后 进行 k%len 次直接交换。
#include
#include
using namespace std;
const int N=2e2+10;
int n, a[N], k, b[N][N], p[N];
char t[N], ans[N];
int main()
{
while(~scanf("%d", &n) && n){
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
p[i] = 0;
b[i][0] = i;
}
for(int i = 1; i <= n; ++i){
int k = 1;
while(1){
++p[i];
b[i][k] = a[b[i][k-1]];
if(b[i][k] == i) break;
++k;
}
}
while(1){
scanf("%d", &k);
if(k == 0) break;
getchar();
string s;
getline(cin,s);
for(int i = 0; i < s.size(); ++i) t[i+1] = s[i];
for(int i = s.size() + 1; i <= n; ++i) t[i] = ' ';
t[n+1]='\0';
//cout<
第二种
#include
#include
using namespace std;
const int N=2e2+10;
int n, a[N], k, b[N][N], change[N], vis[N], num[N], len;
char t[N], ans[N];
int main()
{
while(~scanf("%d", &n) && n){
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
vis[i] = 0;
num[i] = 0;
}
len = 0;
for(int i = 1; i <= n; ++i){
if(!vis[i]){
int now = i;
++len;
while(!vis[now]){
b[len][num[len]++] = now;
vis[now] = 1;
now = a[now];
}
}
}
// for(int i = 1; i < len; ++i) {
// printf("i:%d num:%d\n",i,num[i]);
// for(int j = 0; j < num[i]; ++j) printf("%d ",b[i][j]);
// puts("");
// }
while(1){
scanf("%d", &k);
if(k == 0) break;
getchar();
string s;
getline(cin,s);
for(int i = 0; i < s.size(); ++i) t[i+1] = s[i];
for(int i = s.size() + 1; i <= n; ++i) t[i] = ' ';
t[n+1]='\0';
//cout<