Description
给定一个排列和排列上面每一个点的颜色
定义排列乘法 \(c=a \times b \rightarrow c[i]=b[a[i]]\)
由此我们还可以定义排列的幂
定义无穷环:\(p[p[\dots]]=p[i]\) (循环呗)
求是不是有一个无穷环的 \(k\) 次幂使得 环上的点的颜色都相等
Solution
直接对着 \(p\) 排列处理,先处理出来每个无穷环(这里 \(O(n)\) 完事)
然后我们找规律,发现把每一个环真的看成“环”之后
它的 \(k\) 次幂就是:环上的点向其k个后继连边
这是个关键结论(我去这场全是结论题)
发现之后预处理质因数(就是环长的因数)然后就可以暴力跑了
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=2e5+10;
int n,p[N],c[N],vis[N],ans=1e15+10;
inline int solve(vector<int> &a)
{
vector<int> d;
int sz=a.size();
for(int i=1;i*i<=sz;++i)
{
if(sz%i==0)
{
d.push_back(i);
if(i*i<sz) d.push_back(sz/i);
}
}
sort(d.begin(),d.end()); int s2=d.size();
for(int t=0;t<s2;++t)
{
int k=d[t];
for(int i=0;i<k;++i)
{
bool fl=1;
for(int j=i;j<sz;j+=k) if(a[i]!=a[j]){fl=0; break;}
if(fl) return k;
}
}
return sz;
}
inline void work()
{
n=read(); ans=1e15+10;
for(int i=1;i<=n;++i) vis[i]=0;
for(int i=1;i<=n;++i) p[i]=read();
for(int i=1;i<=n;++i) c[i]=read();
for(int i=1;i<=n;++i)
{
if(!vis[i])
{
vector<int> tmp;
tmp.push_back(c[i]); vis[i]=1;
for(int j=p[i];j!=i;j=p[j]) tmp.push_back(c[j]),vis[j]=1;
ans=min(ans,solve(tmp));
}
} cout<<ans<<endl;
return ;
}
signed main()
{
int T=read(); while(T--) work();
return 0;
}
}
signed main(){return yspm::main();}