AT_arc110_f

为啥这种题大半的题解会都是一样的?来个不同做法的。

首先可以发现,对于一个固定位置操作若干次大概是能使这个位置变成任意一个数的。于是有个猜测的做法:倒序枚举 ii 不断对 00 操作直到 P0=iP_0=i,然后再操作一次使 Pi=iP_i=i

试了一下发现不太行。因为如果此时 a0=0a_0=0 就怎么也动不了了。然后发现 00 其实非常不好,但是发现,可以通过操作若干次数字 n1n-1 的方式使 PP 循环位移,于是先不断操作 n1n-1 使 00 固定到 Pn1P_{n-1} 的位置。

这一步似乎也可以通过不断操作位置 n1n-1 做到。

然后考虑依次使 n2,n3,,2,1n-2,n-3,\cdots,2,100 再到对应位置。此时又发现一个问题:当 P0=n1P_0=n-1 的时候又会出问题。

但是发现这个时候好操作很多:只需要不断操作数字 n1n-1,使它去到还没归位的数的末尾。然后变成不断操作 11 即可。再发生一次就变成不断操作 22,以此类推。

最后再不断操作数字 n1n-1,整个 PP 满足要求即可。

code:

int n,m,a[N],p[N];
vector<int> ans;
il void work(int x){
	ans.eb(x);
	int y=(x+a[x])%n;
	swap(p[a[x]],p[a[y]]);
	swap(a[x],a[y]);
}
void Yorushika(){
	read(n);
	rep(i,0,n-1){
		read(a[i]);
		p[a[i]]=i;
	}
	while(a[n-1]){
		work(p[n-1]);
	}
	int x=0;
	drep(i,n-2,1){
		while(a[x]!=i&&a[(x+i)%n]!=i){
			if(a[x]==n-1){
				drep(j,n-2,i){
					work(p[n-1]);
				}
				x=(x+1)%n;
			}else{
				work(x);
			}
		}
		if(a[x]==i){
			work(x);
		}
	}
	while(a[0]||a[n-1]!=n-1){
		work(p[n-1]);
	}
	printf("%d\n",ans.size());
	for(int i:ans){
		printf("%d\n",i);
	}
}
signed main(){
	int t=1;
	//read(t);
	while(t--){
		Yorushika();
	}
}