CF1327D Infinite Path 抽象代数
题意:
给定一个置换 \(p\) ,求置换的最小 \(k\) 次幂,满足 \(\exists i,c[i]=c[p^k[i]]=c[p^k[p^k[i]]]=...\)
题解:
先将置换写成若干轮换乘积的形式,那么每个轮换都是一个模x剩余加法群
题目式子可以简化为 \(\exists i,c[i]=c[p^k[i]]=c[p^{2k}[i]]=...\) ,即在一个加法群里找一个子群,其元素被集合 \(C\) 包含
那么枚举 \(x\) 因子,暴力判断即可, \(O(n \sqrt {n})\)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#define INF 1e9+7
#define ll long long
using namespace std;
int n,ans,tot;
int p[200001],c[200001],fl[200001];
vector <int> h[200001];
void work(int i,int k,int l)
{
int tc,fl;
for(int j=1;j<=k;j++)
{
tc=c[h[i][j-1]];
fl=0;
for(int p=j+k;p<=l;p+=k)if(c[h[i][p-1]]!=tc){fl=1;break;}
if(!fl){ans=min(ans,k);return;}
}
}
void solve()
{
for(int i=1;i<=tot;i++)h[i].clear();
tot=0;
for(int i=1;i<=n;i++)fl[i]=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&p[i]);
for(int i=1;i<=n;i++)scanf("%d",&c[i]);
for(int i=1;i<=n;i++)
{
if(!fl[i])
{
tot++;
fl[i]=tot;
h[tot].push_back(i);
for(int j=p[i];j!=i;j=p[j])
{
fl[j]=tot;
h[tot].push_back(j);
}
}
}
ans=n;
for(int i=1;i<=tot;i++)
{
int l=h[i].size();
for(int j=1;j*j<=l;j++)
{
if(l%j==0)
{
work(i,j,l);
if(j!=l/j)work(i,l/j,l);
}
}
}
printf("%d\n",ans);
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}