题目链接
这题要考虑找循环节,我们不难发现,在传松的过程中,一定会形成循环节,但是循环节有两种:
1.所有数循环一次,即循环节长度为
n
n
n
2.部分数构成循环,即循环节长度为
t
,
(
t
<
n
)
t,(t<n)
t,(t<n)
下面考虑记录传送路径,那么何时停止最合理呢,我是用数组
v
i
s
vis
vis 记录每个数出现的次数,如果
v
i
s
[
i
]
=
3
vis[i]=3
vis[i]=3 了,那么肯定已经形成循环节了(读者自行考虑),那么只需分类讨论即可,知道循环节的长度
t
t
t 之后只需用
k
%
t
k\%t
k%t 即可求出位置,AC代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int n;
ll k;
cin >> n >> k;
int a[n + 1];
for (int i = 1; i <= n; i++)
cin >> a[i];
int ans[n + 1], cnt = 1, vis[n + 1] = {0};
for (int i = 1;; i = a[i]) {
vis[i]++;
if (vis[i] == 3) break;
ans[cnt++] = i;
}
if (vis[ans[1]] == 2) cout << ans[(k + 1) % (cnt - 1) == 0 ? cnt - 1 : (k + 1) % (cnt - 1)];
else {
int pos, t;
for (int i = 1; i < cnt; i++)
if (vis[ans[i]] == 3) {
pos = i;
break;
}
for (int i = pos + 1; i < cnt; i++)
if (ans[i] == ans[pos]) {
t = i - pos;
break;
}
if (k <= pos - 1) cout << ans[k + 1];
else cout << ans[((k + 1 - pos + 1) % t == 0 ? t : (k + 1 - pos + 1) % t) + pos - 1];
}
return 0;
}