神奇的排列:算法详解及C++代码实现
神奇的排列:算法详解及C++代码实现
问题描述
对于一个长度为 2n 的排列 p_1,p_2,...,p_{2n},定义数组 s 为 p 中两两分组以后每个组的数字之和,即 s_i=p_{2i-1}+p_{2i},可以发现 s 的长度为 n。若 s 是一个连续严格递增数列,则我们称排列 p 为一个神奇的排列。
现在我们给定一个数字 n,请给出一个长度为 2n 可能的神奇的排列 p。
输入格式
第一行一个数字 T,代表有 T 组数据。
接下来 T 行,每行一个整数 N。
输出格式
如果存在满足题意的排列,请输出 YE5,并且在下一行输出一个可能的排列。如果不存在,请输出 N0。
样例 #1
样例输入 #1
3
1
2
5
样例输出 #1
YE5
2 1
N0
YE5
6 3 8 2 10 1 7 5 9 4
提示
数据范围
对于 10% 的数据,N 全为偶数。
对于另外 30% 的数据,T=1。
对于 60% 的数据,1≤T≤50,N≤500。
对于 100% 的数据,1≤T≤500,1≤N≤10^5,且每组数据中,∑N≤10^5。
提示
排列:长为 N 的排列指的是由 1 ~ N 组成的数列,比如 N=3 的排列有:1 2 3、1 3 2、2 1 3、2 3 1、3 1 2、3 2 1等共 6 个。
连续严格递增数列:对于整个数列都有第 i 个数字 a_i 和第 i+1 个数字 a_{i+1},a_{i+1}=a_i+1。
算法分析
-
奇偶性判定: 首先,我们观察到如果
N是奇数,则无法构造出满足题意的排列。这是因为,如果N是奇数,则2N是奇数,排列p的长度为奇数,无法进行两两分组。因此,当N为奇数时,直接输出N0。 -
构造神奇排列: 当
N为偶数时,我们可以构造一个神奇的排列。具体方法如下:- 初始化一个长度为
2N的数组p,将1到2N的数字依次填入。 - 将
p中的奇数位置和偶数位置的元素进行交换。
- 初始化一个长度为
-
输出结果: 构造完排列
p后,输出YE5和排列p。
C++ 代码实现
#include <iostream>
#include <vector>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int N;
cin >> N;
// 如果 N 为奇数,不存在满足题意的排列
if (N % 2 != 0) {
cout << 'N0' << endl;
continue;
}
// 构造一个满足题意的排列
vector<int> p(2 * N);
for (int i = 0; i < 2 * N; i++) {
p[i] = i + 1;
}
for (int i = 0; i < 2 * N; i += 2) {
swap(p[i], p[i + 1]);
}
// 输出排列
cout << 'YE5' << endl;
for (int i = 0; i < 2 * N; i++) {
cout << p[i] << ' ';
}
cout << endl;
}
return 0;
}
总结
本文详细介绍了“神奇的排列”问题,并给出了一个简单的算法和 C++ 代码实现。通过分析问题本质,我们可以高效地构造满足条件的排列。
原文地址: https://www.cveoy.top/t/topic/qnA0 著作权归作者所有。请勿转载和采集!