Atcoder Grand Contest 031 D - A Sequence of Permutations(置换+猜结论)

Atcoder 题面传送门 & 洛谷题面传送门

猜结论神题。

首先考虑探究题目中 \(f\) 函数的性质,\(f(p,q)_{p_i}=q_i\leftarrow f(p,q)\circ p=q\),其中 \(\circ\) 为两个置换的复合\(a\circ b\) 为满足 \(p_{i}=a_{b_i}\) 的置换 \(p\),有点类似于函数的复合,u1s1 我一直把它当作乘法运算,因此总没搞清楚,心态爆炸……等式两边同乘 \(p\) 的复合逆 \(p^{-1}\) 可得 \(f(p,q)=q\circ p^{-1}\)。顺带一提复合满足性质 \((p\circ q)^{-1}=q^{-1}\circ p^{-1}\),这个对后面打表找规律有很大作用。

接下来考虑探究置换序列 \(a\) 的性质,我们不妨根据刚刚的性质先写出 \(a\) 的前几项看看瞧:

\[a_1=p \]

\[a_2=q \]

\[a_3=q\circ p^{-1} \]

\[a_4=q\circ p^{-1}\circ q^{-1} \]

\[a_5=q\circ p^{-1}\circ q^{-1}\circ p\circ q^{-1} \]

\[a_6=q\circ p^{-1}\circ q^{-1}\circ p\circ p\circ q^{-1} \]

\[\cdots \]

注意到这东西是一个类似于线性递推的东西,并且此题 \(k\) 高达 \(10^9\),因此暴力推下去肯定是不行的,不过注意到相邻两项的 \(p,q\) 之间存在一些联系,具体来说,下一项实际上是对上一项进行如下变换:

  • 将所有 \(p\)\(q\) 代替,\(p^{-1}\)\(q^{-1}\) 代替
  • 将所有 \(q\)\(q\circ p^{-1}\) 代替,\(q^{-1}\)\(p\circ q^{-1}\) 代替

那有人就问了,知道这个性质有什么用呢?你就算做了这样一个转化,还不照样还是要递推吗?

这里又有一个考验眼力的地方,注意到 \(a_5\) 中出现了一个式子叫做 \(q\circ p^{-1}\circ q^{-1}\circ p\),我们不妨对其做一遍上面的变换,可得 \((q\circ p^{-1})\circ q^{-1}\circ (p\circ q^{-1})\circ q\)消一下发现它就是 \(q\circ p^{-1}\circ q^{-1}\circ p\),也就是说从 \(a_5\) 开始出现的 \(q\circ p^{-1}\circ q^{-1}\circ p\) 在变换前后不会发生变化,记 \(A=q\circ p^{-1}\circ q^{-1}\circ p\),继续往下写几项可得:

\[a_5=A\circ q^{-1} \]

\[a_6=A\circ p\circ q^{-1} \]

\[a_7=A\circ q\circ p\circ q^{-1} \]

\[a_8=A\circ q\circ p^{-1}\circ q\circ p\circ q^{-1} \]

发现了什么?\(p^{-1}\circ q\circ p\circ q^{-1}\) 就是 \(A^{-1}\),因此 \(a_8\) 就等于 \(A\circ q\circ A^{-1}\),按照上面的方式 \(a_7\) 也可变形为 \(A\circ p\circ A^{-1}\)

\(A,A^{-1}\) 在变换前后都可看作不动点,因此 \(a\) 序列可以看作类周期性变化的,即 \(a_n=A\circ a_{n-6}\circ A^{-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;
}
posted @ 2021-04-29 16:00  tzc_wk  阅读(55)  评论(1编辑  收藏  举报