CF1741B Funny Permutation

更好的阅读体验

题链:cf lugou

奇异构造。

Description

构造一个 \(1\) ~ \(n\) 的排列 \(p\),使得 \(\forall i\in\left[1, n\right]\) 满足存在邻居为 \(a_i\pm 1\)\(a_i\not=i\)

Analysis

构造题。分类讨论。此处的构造方式仅为个人观点,亦有其他构造可能。

  1. \(n\) 为偶数:直接降序输出 \(n\)\(1\),易证满足条件。

  2. \(n\) 为奇数:此情况略复杂,因为直接倒序输出会导致 \(a_\frac{n+1}{2}=\frac{n+1}{2}\)
    考虑在中间数处扭转。下面再分两类:

    1. \(\lfloor\frac{n}{2}\rfloor\) 为奇数,此处以 \(7\) 为例,得 \(7,6,4,5,3,2,1\),很容易发现在 \(4,5\) 的位置发生了局部扭转。故得应在第 \(\frac{n-1}{2}\)\(\frac{n+1}{2}\) 处进行扭转。
    2. \(\lfloor\frac{n}{2}\rfloor\) 为奇数,此处以 \(5\) 为例,得 \(5,4,1,2,3\),很容易发现在 \(4,1\) 的位置发生了整体扭转。故得应在后半部分即第 \(\frac{n-1}{2}\)\(n\) 个数倒序。

注意:通过枚举不难发现 \(n=3\) 时无解,记住特判。

Code

#include <stdio.h>
inline void Solve() {
	int n; scanf("%d", &n);
	if (n == 3) {puts("-1"); return;}
	if (n & 1) { //1
		if (n / 2 & 1) { //1-i
			for (int i = 1; i <= n / 2; ++i) printf("%d ", n - i + 1);
			printf("%d %d ", n - (n / 2 + 2) + 1, n - (n / 2 + 1) + 1);
			for (int i = n - (n / 2 + 2); i >= 1; --i) printf("%d ", i);
			putchar('\n');
		}
		else { //1-ii
			for (int i = 1; i <= n / 2; ++i) printf("%d ", n - i + 1);
			for (int i = 1; i < n - n / 2 + 1; ++i) printf("%d ", i);
			putchar('\n');
		}
	}
	else { //2
		for (int i = n; i >= 1; --i) printf("%d ", i);
		putchar('\n');
	}
}
int main(void) {
	int T; for (scanf("%d", &T); T--; ) Solve();
	return 0;
}

The end. Thanks.

(路过一点

posted @ 2022-10-14 16:39  Dry_ice  阅读(40)  评论(0)    收藏  举报