养成了看群决定有没比赛的习惯
因为今天群里没动静以为今天没比赛 导致这场杭电没去做 对不住队友Q^Q
permutation 1
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
A sequence of length n is called a permutation if and only if it’s composed of the first n positive integers and each number appears exactly once.
Here we define the “difference sequence” of a permutation p1,p2,…,pn as p2−p1,p3−p2,…,pn−pn−1. In other words, the length of the difference sequence is n−1 and the i-th term is pi+1−pi
Now, you are given two integers N,K. Please find the permutation with length N such that the difference sequence of which is the K-th lexicographically smallest among all difference sequences of all permutations of length N.
Input
The first line contains one integer T indicating that there are T tests.
Each test consists of two integers N,K in a single line.
-
1≤T≤40
-
2≤N≤20
-
1≤K≤min(104,N!)
Output
For each test, please output N integers in a single line. Those N integers represent a permutation of 1 to N, and its difference sequence is the K-th lexicographically smallest.
Sample Input
7
3 1
3 2
3 3
3 4
3 5
3 6
20 10000
Sample Output
3 1 2
3 2 1
2 1 3
2 3 1
1 2 3
1 3 2
20 1 2 3 4 5 6 7 8 9 10 11 13 19 18 14 16 15 17 12
Solution
因为k最多只到1e4,将‘difference sequence’ 按照字典序暴力搜索就能过了
开始想着是n的阶乘,看了下范围,发现还对1e4取了个min。。
搜索时只需考虑数值的相对情况,无需考虑数值本身是多少
由于按照字典序的顺序,确认下一个数值时优先从小的开始,总能确保是按字典序
由于按照差值的字典序,搜索时要尽可能确保前面的相对差值不变的情况下,改变后面的数值,到迫不得已时才回溯改变前面的
核心是要搜索只考虑数值的差值,而不需考虑数字本身是多少
例如输入: 1 5 120
搜索历程:
Array res: 5 1 2 3 4 idest 5 1 2 3 4 difference -4 1 1 1
Array res: 5 1 2 4 3 idest 5 1 2 4 3 difference -4 1 2 -1
Array res: 5 1 3 2 4 idest 5 1 3 2 4 difference -4 2 -1 2
Array res: 5 1 3 4 2 idest 5 1 3 4 2 difference -4 2 1 -2
Array res: 5 1 4 2 3 idest 5 1 4 2 3 difference -4 3 -2 1
Array res: 5 1 4 3 2 idest 5 1 4 3 2 difference -4 3 -1 -1
Array res: 5 2 1 3 4 idest 5 2 1 3 4 difference -3 -1 2 1
Array res: 5 2 1 4 3 idest 5 2 1 4 3 difference -3 -1 3 -1
Array res: 5 2 3 1 4 idest 5 2 3 1 4 difference -3 1 -2 3
Array res: 5 2 3 4 1 idest 5 2 3 4 1 difference -3 1 1 -3
Array res: 5 2 3 4 6 idest 4 1 2 3 5 difference -3 1 1 2
Array res: 5 2 3 6 4 idest 4 1 2 5 3 difference -3 1 3 -2
Array res: 5 2 4 1 3 idest 5 2 4 1 3 difference -3 2 -3 2
Array res: 5 2 4 3 1 idest 5 2 4 3 1 difference -3 2 -1 -2
搜索里程中只需要考虑的是数值的差,因此若res数组不是 1 到 n的数, 只需要将所有数都“向左平移” 即可得到答案(平移不改变差)
例如 5 2 3 4 6, 平移得到 4 1 2 3 5(全部减一)
具体见代码
AC Code
/*
* Copyright (c) 2019 Ng Kimbing, HNU, All rights reserved. May not be used, modified, or copied without permission.
* @Author: Ng Kimbing, HNU.
* @LastModified:2019-08-05 T 19:24:53.514 +08:00
*/
import static ACMProblems.ACMIO.nextInt;
import static ACMProblems.ACMIO.out;
public class HDOJMain {
private static int n, k, cnt;
private static final int maxn = 25;
static boolean used[] = new boolean[maxn];
private static int res[] = new int[maxn];
private static void printAnswer(int bias) {
out.print(res[0] - bias + 1);
for (int i = 1; i < n; ++i)
out.print(" " + (res[i] - bias + 1));
out.println();
}
/**
* Search in lexicographic order of the number difference,
* While dfs-ing, try to keep the difference of the number that has been determined before unchanged,
* and modify the numbers that have not been determined yet.
* Since what we want is lexicographical order of the ‘difference sequence’,
* we only need to consider the relativeity of the numerical difference, rather than the value itself.
*
* @param currPos current position
* @param currMin the minimum number of current paths
* @param currMax The maximum number of current paths
* @return Returns whether the answer has been found
*/
private static boolean dfs(int currPos, int currMin, int currMax) {
if (currPos == n) {
++cnt;
if (cnt == k) {
printAnswer(currMin);
return true;
}
return false;
}
for (int currNum = currMax - n + 1; currNum < currMin + n; ++currNum) {
if (!used[currNum]) {
used[currNum] = true;
res[currPos] = currNum;
if (dfs(currPos + 1, Math.min(currMin, currNum), Math.max(currMax, currNum))) {
used[currNum] = false;
return true;
}
used[currNum] = false;
}
}
return false;
}
private static void solve() {
cnt = 0;
res[0] = n;
used[n] = true;
dfs(1, n, n);
used[n] = false;
}
public static void main(String[] args) throws Exception {
int t;
for (t = nextInt(); t-- != 0; ) {
n = nextInt();
k = nextInt();
solve();
}
out.flush();
}
}