#include <iostream> #include <string> #include <map> using namespace std; long long INF = (long long) 1e18+5; std::map<std::pair<int,int>, long long> memo; void setMemo(int n, long long k, long long val){ long max_inv = 1L * n * (n - 1) / 2; k = min(k, max_inv - k); memo[std::make_pair(n, (int)k)] = val; } long long getMemo(int n, long long k) { long long max_inv = n * (n - 1) / 2; if (max_inv < k) return 0L; k = min(k, max_inv - k); if (memo.find(std::make_pair(n, (int)k)) == memo.end()){ return INF; } return memo[std::make_pair(n, (int)k)]; } long long getFor(int n, long long k) { long long ans = 0; for (int j = 0; j < n && k - j >= 0; j++) { ans += getMemo(n - 1, k - j); if (ans >= INF) return INF; } return ans; } int main() { int N; long long K; cin >> N; cin >> K; setMemo(0, 0, 1); long long N_INV = 1L * N * (N - 1) / 2; if (N_INV % 2 != 0) { cout << "NIE" << endl; return 0; } for (int n = 1; n <= N; n++) { bool less = true; long long MAX_N_INV = 1L * n * (n - 1) / 2; for (long long k = 0; k <= MAX_N_INV / 2 && less; k++) { long long nk = getFor(n, k); if (nk == INF) { less = false; } else { setMemo(n, k, nk); setMemo(n, MAX_N_INV - k, nk); } } } if (getMemo(N, N_INV / 2) < K) { cout << "NIE" << endl; return 0; } int ANS[N]; int index = 0; int available[N]; for (int i = 0; i < N; i++) available[i] = i + 1; long long INV = 1L * N * (N - 1) / 4; while (index < N) { int rem = N - index - 1; int k = 0; int size = sizeof(available) / sizeof(available[0]); for (int i = 0; i < size; i++) { if (available[i] < 0) continue; int NINV = INV - k; if (getMemo(rem, NINV) < K) { // so we cannot fix available[i], but we should subtract number of permutations K -= getMemo(rem, NINV); } else { // we can fix available[i] on index ANS[index] = available[i]; INV = NINV; available[i] = -1; break; } k++; } index++; } cout << "TAK" << endl; cout << ANS[0]; int size = sizeof(ANS) / sizeof(ANS[0]); for (int i=1; i<size; i++){ cout << " " << ANS[i]; } cout << endl; return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #include <iostream> #include <string> #include <map> using namespace std; long long INF = (long long) 1e18+5; std::map<std::pair<int,int>, long long> memo; void setMemo(int n, long long k, long long val){ long max_inv = 1L * n * (n - 1) / 2; k = min(k, max_inv - k); memo[std::make_pair(n, (int)k)] = val; } long long getMemo(int n, long long k) { long long max_inv = n * (n - 1) / 2; if (max_inv < k) return 0L; k = min(k, max_inv - k); if (memo.find(std::make_pair(n, (int)k)) == memo.end()){ return INF; } return memo[std::make_pair(n, (int)k)]; } long long getFor(int n, long long k) { long long ans = 0; for (int j = 0; j < n && k - j >= 0; j++) { ans += getMemo(n - 1, k - j); if (ans >= INF) return INF; } return ans; } int main() { int N; long long K; cin >> N; cin >> K; setMemo(0, 0, 1); long long N_INV = 1L * N * (N - 1) / 2; if (N_INV % 2 != 0) { cout << "NIE" << endl; return 0; } for (int n = 1; n <= N; n++) { bool less = true; long long MAX_N_INV = 1L * n * (n - 1) / 2; for (long long k = 0; k <= MAX_N_INV / 2 && less; k++) { long long nk = getFor(n, k); if (nk == INF) { less = false; } else { setMemo(n, k, nk); setMemo(n, MAX_N_INV - k, nk); } } } if (getMemo(N, N_INV / 2) < K) { cout << "NIE" << endl; return 0; } int ANS[N]; int index = 0; int available[N]; for (int i = 0; i < N; i++) available[i] = i + 1; long long INV = 1L * N * (N - 1) / 4; while (index < N) { int rem = N - index - 1; int k = 0; int size = sizeof(available) / sizeof(available[0]); for (int i = 0; i < size; i++) { if (available[i] < 0) continue; int NINV = INV - k; if (getMemo(rem, NINV) < K) { // so we cannot fix available[i], but we should subtract number of permutations K -= getMemo(rem, NINV); } else { // we can fix available[i] on index ANS[index] = available[i]; INV = NINV; available[i] = -1; break; } k++; } index++; } cout << "TAK" << endl; cout << ANS[0]; int size = sizeof(ANS) / sizeof(ANS[0]); for (int i=1; i<size; i++){ cout << " " << ANS[i]; } cout << endl; return 0; } |