#include <cstdio> #include <set> #include <vector> #include <algorithm> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; typedef long long i64; const int N = 250000 + 10; const i64 INF = 0x3f3f3f3f3f3f3f3fLL; std::vector<i64> f[N]; inline void add(i64 &lhs, i64 rhs) { lhs = std::min(lhs + rhs, INF); } i64 get(int n, i64 m) { i64 t = std::min(m, n * (n - 1LL) / 2 - m); if (t < 0) return 0; return t < f[n].size() ? f[n][t] : INF; } int n; i64 k; tree<int, null_type, std::less<int>, rb_tree_tag, tree_order_statistics_node_update> pool; int main() { scanf("%d%lld", &n, &k); i64 m = n * (n - 1LL) / 2; if (m & 1) { puts("NIE"); return 0; } m >>= 1; f[0].push_back(1); for (int i = 0; i < n; ++i) { int tot = f[i].size() + (f[i].back() == INF ? 0 : i); f[i + 1].resize(tot); for (int j = 0; j < f[i].size(); ++j) for (int k = 0; k <= i && j + k < tot; ++k) add(f[i + 1][j + k], f[i][j]); for (int j = 0; j < tot; ++j) { if (f[i + 1][j] == INF) { f[i + 1].resize(j + 1); break; } } } if (get(n, m) < k) { puts("NIE"); return 0; } for (int i = 1; i <= n; ++i) pool.insert(i); puts("TAK"); for (int i = n; i > 0; --i) { int j = std::max(m - (i - 1LL) * (i - 2LL) / 2, 0LL); for (auto it = pool.find_by_order(j); it != pool.end(); ++it, ++j) { i64 temp = get(i - 1, m - j); if (temp >= k) { printf("%d ", *it); pool.erase(it); m -= j; break; } else { k -= temp; } } } 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 | #include <cstdio> #include <set> #include <vector> #include <algorithm> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; typedef long long i64; const int N = 250000 + 10; const i64 INF = 0x3f3f3f3f3f3f3f3fLL; std::vector<i64> f[N]; inline void add(i64 &lhs, i64 rhs) { lhs = std::min(lhs + rhs, INF); } i64 get(int n, i64 m) { i64 t = std::min(m, n * (n - 1LL) / 2 - m); if (t < 0) return 0; return t < f[n].size() ? f[n][t] : INF; } int n; i64 k; tree<int, null_type, std::less<int>, rb_tree_tag, tree_order_statistics_node_update> pool; int main() { scanf("%d%lld", &n, &k); i64 m = n * (n - 1LL) / 2; if (m & 1) { puts("NIE"); return 0; } m >>= 1; f[0].push_back(1); for (int i = 0; i < n; ++i) { int tot = f[i].size() + (f[i].back() == INF ? 0 : i); f[i + 1].resize(tot); for (int j = 0; j < f[i].size(); ++j) for (int k = 0; k <= i && j + k < tot; ++k) add(f[i + 1][j + k], f[i][j]); for (int j = 0; j < tot; ++j) { if (f[i + 1][j] == INF) { f[i + 1].resize(j + 1); break; } } } if (get(n, m) < k) { puts("NIE"); return 0; } for (int i = 1; i <= n; ++i) pool.insert(i); puts("TAK"); for (int i = n; i > 0; --i) { int j = std::max(m - (i - 1LL) * (i - 2LL) / 2, 0LL); for (auto it = pool.find_by_order(j); it != pool.end(); ++it, ++j) { i64 temp = get(i - 1, m - j); if (temp >= k) { printf("%d ", *it); pool.erase(it); m -= j; break; } else { k -= temp; } } } return 0; } |