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;
}

posted @ 2020-10-23 15:52  worcher  阅读(101)  评论(0编辑  收藏  举报