https://codeforces.com/gym/104270/problem/F

题目要求输出最小字典序的答案

由于要求每轮每人战斗且仅战斗了一次,不难想到第一轮的情况应该是这样的:

1-2 3-4 5-6 7-8 …

也就是说答案矩阵的第一行为

2 1 4 3 6 5 8 7 …

(似乎是正整数数列以2个数为单位交换)

在推导第二行的过程中,我们可以发现第二轮只有在4|k的情况下才有解(最后会提到如何判断非法情况)。最小字典序的选法为

3 4 1 2 7 8 5 6

似乎是相邻两个元素交换,打一个表出来

2 1 4 3 6 5 8 7
3 4 1 2 7 8 5 6
4 3 2 1 8 7 6 5
5 6 7 8 1 2 3 4
6 5 8 7 2 1 4 3
7 8 5 6 3 4 1 2
8 7 6 5 4 3 2 1

假设第0行是 1 2 3 4 5 6 7 8

则后面的每一行分别在前一行的基础上分别按 2 4 2 8 2 4 2 为长度翻转

所以只需要预处理出这样的数列,实现一个翻转函数依次进行翻转

1
2
3
4
5
6
7
void sswap(int len)
{
for(int i=1;i<=1000;i+=len)
{
reverse(tmp+i,tmp+i+len);
}
}

由于最优排列方法是固定的,可以直接生成一个完整的答案矩阵然后取子矩阵输出

关于无解情况的判断

由于要求两人之间不能进行多场战斗,所以k>n-1时无解

由于翻转时有可能会引入大于n的数,这样的情况为非法