题意:
给定长度为n的排列A,和一个整数k
要求找到一个长度为n的排列置换P,满足{1,2,3…,n}进行k次置换之后恰好变成A
输出置换P的一种方案,如果无解则输出-1
数据范围:n<=1e5,1e8<=k<=1e9,保证k是一个质数
解法:
题解:
大概是这样的(不太确定):
对每个环单独计算一次逆元,然后用逆元置换一下A就行了
(Pk中,每轮置换,各个环间相互不影响,因此还原也是相互不影响的)
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=1e5+5;
int mark[maxm];
int ans[maxm];
int a[maxm];
int n,k;
signed main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
vector<int>cir[maxm];
int cnt=0;
for(int i=1;i<=n;i++){
if(!mark[i]){
cnt++;
int x=i;
while(!mark[x]){
mark[x]=1;
cir[cnt].push_back(x);
x=a[x];
}
}
}
for(int i=1;i<=cnt;i++){
int len=cir[i].size();
//计算逆元,逆元一定在[0,len)中,可以暴力
int inv=0;
while(len!=1&&1LL*inv*k%len!=1){//注意判断len!=1
inv++;
}
//
for(int j=0;j<len;j++){
int pos=(j+inv)%len;
ans[cir[i][j]]=cir[i][pos];
}
}
for(int i=1;i<=n;i++){
printf("%d ",ans[i]);
}
return 0;
}