题解 AT4694 [AGC031D] A Sequence of Permutations
Atcoder 题面传送门 & 洛谷题面传送门
猜结论神题。
首先考虑探究题目中 u1s1 我一直把它当作乘法运算,因此总没搞清楚,心态爆炸……等式两边同乘
接下来考虑探究置换序列
注意到这东西是一个类似于线性递推的东西,并且此题
- 将所有
p 用q 代替,p^{-1} 用q^{-1} 代替 - 将所有
q 用q\circ p^{-1} 代替,q^{-1} 用p\circ q^{-1} 代替
那有人就问了,知道这个性质有什么用呢?你就算做了这样一个转化,还不照样还是要递推吗?
这里又有一个考验眼力的地方,注意到 削消一下发现它就是
发现了什么?
矩阵快速幂即可。
总之是一道考验眼力的猜结论神题。
const int MAXN=1e5;
int n,k;
struct perm{
int a[MAXN+5];
perm(){for(int i=1;i<=n;i++) a[i]=i;}
perm operator *(const perm &rhs) const{
perm ret;
for(int i=1;i<=n;i++) ret.a[i]=a[rhs.a[i]];
return ret;
}
} p,q;
perm inv(perm x){
perm ret;
for(int i=1;i<=n;i++) ret.a[x.a[i]]=i;
return ret;
}
perm qpow(perm x,int e){
perm ret;
for(;e;e>>=1,x=x*x) if(e&1) ret=ret*x;
return ret;
}
int main(){
scanf("%d%d",&n,&k);k--;perm ans;
for(int i=1;i<=n;i++) scanf("%d",&p.a[i]);
for(int i=1;i<=n;i++) scanf("%d",&q.a[i]);
perm A=q*inv(p)*inv(q)*p;
if(k%6==0) ans=p;
if(k%6==1) ans=q;
if(k%6==2) ans=q*inv(p);
if(k%6==3) ans=A*inv(p);
if(k%6==4) ans=A*inv(q);
if(k%6==5) ans=A*p*inv(q);
ans=qpow(A,k/6)*ans*qpow(inv(A),k/6);
for(int i=1;i<=n;i++) printf("%d ",ans.a[i]);
return 0;
}