#include <iostream> #include <cstdlib> #include <set> #include <vector> #include <cassert> using namespace std; const long long INF = 2e18; const int N = 250001; vector<long long> dp[N]; void fail() { cout << "NIE\n"; exit(0); } long long get_val(int n, long long k) { long long max_inv = n * (long long)(n-1) / 2; if (k > max_inv) return 0; k = min(k, max_inv-k); return (k >= dp[n].size() ? INF : dp[n][k]); } bool geq(int n, long long k, long long x) { return get_val(n, k) >= x; } const int C = (1<<18); int size[2*C]; int get(int num) { int pos = 1; while (pos < C) { pos *= 2; if (size[pos] <= num) { num -= size[pos]; pos++; } } return pos-C; } void set_vis(int x) { int pos = C+x; while (pos) { size[pos]--; pos /= 2; } } long long get_max_inv(long long n) { return n*(n-1)/2; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); dp[1].push_back(1); for (int n=2; n<N; n++) { long long max_inv = get_max_inv(n); for (int k=0; k<=max_inv; k++) { long long r = 0; if (k == 0) r = 1; else if (k > max_inv/2) { r = dp[n][max_inv-k]; } else { r = dp[n][k-1] + dp[n-1][k]; if (k >= n) r -= dp[n-1][k-n]; } if (r >= INF) r = INF; dp[n].push_back(r); if (r == INF) break; } } long long n, k; cin >> n >> k; long long max_inv = get_max_inv(n); if (max_inv % 2) fail(); long long inv = max_inv / 2; for (int i=1; i<=n; i++) size[C+i] = 1; for (int i=C-1; i>0; i--) size[i] = size[2*i] + size[2*i+1]; if (!geq(n, inv, k)) fail(); cout << "TAK\n"; for (int i=1; i<=n; i++) { int x = get(0), pos = 0; while (true) { if (geq(n-i, inv, k)) { set_vis(x); cout << x << " "; break; } long long max_inv = get_max_inv(n-i); if (max_inv < inv) { int diff = inv - max_inv; x = get(pos+diff); inv -= diff; pos += diff; continue; } k -= get_val(n-i, inv); inv--; pos++; x = get(pos); } } cout << "\n"; 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 106 107 108 109 110 | #include <iostream> #include <cstdlib> #include <set> #include <vector> #include <cassert> using namespace std; const long long INF = 2e18; const int N = 250001; vector<long long> dp[N]; void fail() { cout << "NIE\n"; exit(0); } long long get_val(int n, long long k) { long long max_inv = n * (long long)(n-1) / 2; if (k > max_inv) return 0; k = min(k, max_inv-k); return (k >= dp[n].size() ? INF : dp[n][k]); } bool geq(int n, long long k, long long x) { return get_val(n, k) >= x; } const int C = (1<<18); int size[2*C]; int get(int num) { int pos = 1; while (pos < C) { pos *= 2; if (size[pos] <= num) { num -= size[pos]; pos++; } } return pos-C; } void set_vis(int x) { int pos = C+x; while (pos) { size[pos]--; pos /= 2; } } long long get_max_inv(long long n) { return n*(n-1)/2; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); dp[1].push_back(1); for (int n=2; n<N; n++) { long long max_inv = get_max_inv(n); for (int k=0; k<=max_inv; k++) { long long r = 0; if (k == 0) r = 1; else if (k > max_inv/2) { r = dp[n][max_inv-k]; } else { r = dp[n][k-1] + dp[n-1][k]; if (k >= n) r -= dp[n-1][k-n]; } if (r >= INF) r = INF; dp[n].push_back(r); if (r == INF) break; } } long long n, k; cin >> n >> k; long long max_inv = get_max_inv(n); if (max_inv % 2) fail(); long long inv = max_inv / 2; for (int i=1; i<=n; i++) size[C+i] = 1; for (int i=C-1; i>0; i--) size[i] = size[2*i] + size[2*i+1]; if (!geq(n, inv, k)) fail(); cout << "TAK\n"; for (int i=1; i<=n; i++) { int x = get(0), pos = 0; while (true) { if (geq(n-i, inv, k)) { set_vis(x); cout << x << " "; break; } long long max_inv = get_max_inv(n-i); if (max_inv < inv) { int diff = inv - max_inv; x = get(pos+diff); inv -= diff; pos += diff; continue; } k -= get_val(n-i, inv); inv--; pos++; x = get(pos); } } cout << "\n"; return 0; } |