2020牛客暑期多校训练营(第二场) J-Just Shuffle【置换群】

传送门

题意

已知({1,2,...,n})按照(P)经过(k)次变化之后得到(A),现在给定(A)(k),求({1,2,...,n})按照(P)经过(1)次变化之后的结果(B)

题解

主要的知识点是置换群,当然我一点都不了解,所以这道题直接GG。
可以得知,(B^k=A),根据置换群与逆元可知,(A^{k^{-1}}=B)。设(A)中所有环是(r_1,r_2,...,r_m),本来(k^{-1})应该是(lcm{|r_1|,|r_2|,...,|r_m|})下的逆元,但其实可以对每个环分开考虑,所以对于每个环(r_i),求出(k)在模(|r_i|)下的逆元(inv_i),然后对环上每个点变换(inv_i)次就行了。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n,a[N],ans[N],vis[N],k;
vector<int> vec;

void dfs(int u){
	if(vis[u]) return;
	vis[u]=1;
	vec.push_back(u);
	dfs(a[u]);
}

int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int w=1;w<=n;w++){
		if(vis[w]) continue;
		vec.clear();
		dfs(w);
		int siz=vec.size(),inv;
		for(int i=1;i<=siz;i++)if(1ll*k*i%siz==1) inv=i;
		for(int i=0;i<siz;i++) ans[vec[i]]=vec[(i+inv)%siz];
	}
	for(int i=1;i<=n;i++) printf("%d ",ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/BakaCirno/p/13384067.html