题目大意思:
给定一个数的next值,问最小的k值,使得每次进行k次操作得到的数都是一样的。
将每个位置i记为点i
记circle[i]为从i出发出现环的环内元素,我们的任务就是求这些数的最小公倍数lcm,还要考虑‘6’型循环的情况,这个我们只需要求最大的多余长度之后对lcm向上取整就好了
#include<cstdio>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 205;
int next[maxn],vis[maxn];
LL circle[maxn],maxv = 0;
LL gcd(LL a,LL b){
return b == 0 ? a : gcd(b,a % b);
}
int main(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",&next[i]);
for(int i = 1; i <= n; i++){
stack<int>Stack;
memset(vis,0,sizeof(vis));
int pos = i;
circle[i] = 0LL;
while(!vis[pos]){
vis[pos] = 1;
Stack.push(pos);
pos = next[pos];
}
while(true){
int e = Stack.top(); Stack.pop();
circle[i] ++;
if(e == pos) break;
}
maxv = max(maxv,(LL)Stack.size());
}
LL lcm = circle[1];
for(int i = 2; i <= n; i++){
lcm = lcm / gcd(lcm,circle[i]) * circle[i];
}
LL temp = maxv / lcm;
if(maxv % lcm || maxv == 0) temp ++;
LL ans = temp * lcm;
printf("%lld\n",ans);
return 0;
}