Codeforces1327D Infinite Path

Description

link

给定一个排列和排列上面每一个点的颜色

定义排列乘法 (c=a imes b ightarrow 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();}
原文地址:https://www.cnblogs.com/yspm/p/12563724.html