版权声明:Fashion Education https://blog.csdn.net/ModestCoder_/article/details/86774484
原题传送门
题目描述
现在有n个座位编号为11至nn,这些小朋友也编号11至nn。一开始所有小朋友都坐在相应的座位上。HKE的游戏可用一个n的排列A(A_1,A_2\cdots A_nA(A
1
,A
2
⋯A
n
)表示。一轮游戏时,对于所有的1\leq i\leq n1≤i≤n,坐在位置ii上的小朋友坐到位置A_iA
i
上。
现在游戏进行了kk轮,HKE想知道游戏结束后,位置1,2\cdots n1,2⋯n分别坐了几号小朋友?
输入输出格式
输入格式:
第一行n,kn,k。
第二行A_1,A_2\cdots A_nA
1
,A
2
⋯A
n
输出格式:
一行n个数表示位置1,2……n1,2……n上的小朋友的编号
输入样例#1:
5 5
2 3 1 5 4
输出样例#1:
2 3 1 5 4
输入样例#2:
5 4
2 3 1 5 4
输出样例#2:
3 1 2 4 5
说明
30%的数据,
100%的数据,
正解是倍增,复杂度
,这里有一种朴素的
做法
用基本的图论做法,找环,并同时计算出环的长度
然后按环,一个环一个环的处理,每个环中的元素往后一起移
个位子,所以这样能做到每个点只走一遍
Code:
/*
5 5
2 3 1 5 4
*/
#include <bits/stdc++.h>
#define res register int
#define ll long long
#define maxn 100010
using namespace std;
int n, m, a[maxn], loop[maxn], print[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-') w = -1; c = getchar();
}
while (c >= '0' && c <= '9') s = (s << 1) + (s << 3) + (c ^ 48), c = getchar();
return s * w;
}
inline int calc(int u, int s){
loop[u] = s;
if (loop[a[u]]) return s;
loop[u] = calc(a[u], s + 1);
return loop[u];
}
int main(){
n = read(), m = read();
for (res i = 1; i <= n; ++ i) a[i] = read();
for (res i = 1; i <= n; ++ i) if (!loop[i]) loop[i] = calc(i, 0);
for (res i = 1; i <= n; ++ i)
if (!print[i]){
int u = i, v = i;
for (ll k = m % loop[i]; k; -- k) v = a[v];
while (!print[v]){
print[v] = u; u = a[u]; v = a[v];
}
}
for (res i = 1; i <= n; ++ i) printf("%d ", print[i]);
return 0;
}