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;
}