Ignatius and the Princess II
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1862 Accepted Submission(s): 1119
"Now I will show you the first problem." feng5166 says, "Given a sequence of number 1 to N, we define that 1,2,3...N-1,N is the smallest sequence among all the sequence which can be composed with number 1 to N(each number can be and should be use only once in this problem). So it's easy to see the second smallest sequence is 1,2,3...N,N-1. Now I will give you two numbers, N and M. You should tell me the Mth smallest sequence which is composed with number 1 to N. It's easy, isn't is? Hahahahaha......"
Can you help Ignatius to solve this problem?
发现 7! < 10000 < 8!
如果 n > 8,第一个排序是 1, 2, ..., n - 1, n,而且前 10000 个排序只有最后的 8 个数可能发生变动,所以可以只对后面 8 个数模拟排序,若模拟次数是 X,那么时间复杂度是 O(X*8)。
接下来是模拟次数 X:
n 个数的排序,他的最后一个排序一定是 n, n - 1, ..., 2, 1,所以我们可以预先知道的若干个排序是第1!, 2!, 3! ... 个。
比如 1~7 的第 1!, 2!, 3! ... 个排序分别是:
1, 2, 3, 4, 5, 6, 7
1, 2, 3, 4, 5, 7, 6
1, 2, 3, 4, 7, 6, 5
1, 2, 3, 7, 6, 5, 4
1, 2, 7, 6, 5, 4, 3
1, 7, 6, 5, 4, 3, 2
7, 6, 5, 4, 3, 2, 1
这样模拟次数大约可以下降到 O(m / 8)。
总时间复杂度大约是 O(m / 8 * 8)
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
int n, m;
int fac [9] = {1, 1, 2, 6, 24, 120, 720, 720*7, 720*56};
while (scanf ("%d%d", &n, &m) == 2) {
assert (m < fac [8]);
vector <int> perm;
while ((int)perm.size() < 8 && (int)perm.size() < n) {
perm.push_back (perm.size() + 1);
}
int i = 0;
while (fac [++i] <= m) {}
--i;
assert (i <= (int)perm.size());
reverse (perm.end() - i, perm.end());
int p = fac [i];
while (p++ < m) {
#ifdef _DEBUG
bool b =
#endif
next_permutation (perm.begin(), perm.end());
#ifdef _DEBUG
assert (b);
#endif
}
if (n <= 8) {
for (int k=0; k<(int)perm.size(); ++k) {
printf ("%d%s", perm[k], k==(int)perm.size()-1 ? "\n" : " ");
}
} else {
for (int k=0; k<n-8; ++k) {
printf ("%d ", k + 1);
}
for (int k=0; k<8; ++k) {
printf ("%d%s", perm[k] + n - 8, k==7 ? "\n" : " ");
}
}
}
return 0;
}