P2582
很好的一道题。感觉评蓝有点低了。
首先注意到一个性质:如果
以此类推,我们可以推出:对任意的
也就是说,如果我们将每个
方便起见,我们设建图之后点
这样一来,如果
即
那么,我们首先建图,对每个点求出它的
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
const int MN=8e5+5;
using namespace std;
int n,f[MN],g[MN];
bool vis[MN];
int mn[MN],s[MN];
int dfs(int x){
if(vis[x])return 0;
vis[x]=1;
return dfs(f[x])+1;
}
void dfs2(int x,int sz){
if(vis[x])return ;
vis[x]=1,s[x]=sz;
dfs2(f[x],sz);
}
void dfs3(int x,int y){
if(vis[x])return ;
vis[x]=1,g[x]=y;
dfs3(f[x],f[y]);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>f[i];
for(int i=1;i<=n;i++){
if(!vis[i]){
s[i]=dfs(i);
if(!mn[s[i]])mn[s[i]]=i;
}
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)if(!vis[i])dfs2(i,s[i]);
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
if(!vis[i]){
int Mn=1000000;
for(int j=1;j*j<=s[i];j++){
if(s[i]%j==0){
if(mn[j]>0)Mn=min(Mn,mn[j]);
if(mn[s[i]/j]>0)Mn=min(Mn,mn[s[i]/j]);
}
}
dfs3(i,Mn);
}
}
for(int i=1;i<=n;i++)cout<<g[i]<<" ";puts("");
return 0;
}