#include <bits/stdc++.h> using namespace std; #define int long long using ll = long long; const ll inf = 2e18; const int maxN = 1 << 18; vector<ll> _cnt[maxN]; // vector<ll> _sums[maxN]; ll get(ll n, ll k) { k = min(k, n * (n - 1) / 2 - k); if(k < 0) return 0; if(n == 1) return k == 0; assert(k >= 0); if(_cnt[n].size() <= k) return inf; return _cnt[n][k]; } ll getsum(ll n, ll a, ll b) { a = max(a, 0LL); b = min(b, n * (n - 1) / 2); if(a > n * (n - 1) / 2) return 0; if(a > b) { printf("%lld %lld %lld\n", n, a, b); assert(a <= b); } if((b - a) > 40) return inf; ll res = 0; for(ll i = a; i <= b; ++i) res = min(inf, res + get(n, i)); return res; } ll count(int n, ll k) { // ll res = 0; // for(int in = 0; in < n; ++in) // res = min(get(n - 1, k - in, _cnt) + res, inf); // return res; return getsum(n - 1, k - n + 1, k); } const int r = 1 << 18; int tree[2 * r]; void print_kth(int k) { int x = 1; tree[x]--; while(x < r) { if(tree[2 * x] >= k) x *= 2; else { x = 2 * x + 1; k -= tree[x - 1]; } tree[x]--; } printf("%lld ", x - r); } void gen(ll n, ll k, ll inw) { if(n == 0) return; assert(inw <= n * (n - 1) / 2); // printf("n=%lld, k=%lld, inw=%lld\n", n, k, inw); ll min_b = max(0LL, inw - (n - 1) * (n - 2) / 2); ll a = min_b - 1, b = min(n - 1, inw), avg; while(b - a > 1) { avg = (a + b) / 2; // printf("%lld %lld\n", a, b); assert(avg >= 0); // printf("sum %lld..%lld=%lld\n", inw-avg, inw, getsum(n-1, inw-avg, avg)); if(getsum(n - 1, inw - avg, inw - min_b) < k) a = avg; else b = avg; } if(b) k -= getsum(n - 1, inw - b + 1, inw - min_b); assert(k > 0); print_kth(b + 1); // printf("!!! [b=%lld]\n", b); gen(n - 1, k, inw - b); } #undef int int main() { #define int long long ll n, k; scanf("%lld%lld", &n, &k); for(ll _n = 1; _n <= n; ++_n) for(ll x, sx = 0, _k = 0; _k <= _n * (_n - 1) / 2; ++_k) { x = count(_n, _k); if(x != inf) { _cnt[_n].push_back(x); // if(_k) sx = _sums[_n].back(); // _sums[_n].push_back(min(inf, sx + x)); } else break; } if((n * (n - 1)) & 3 || count(n, n * (n - 1) / 4) < k) { puts("NIE"); return 0; } puts("TAK"); for(int i = 1; i <= n; ++i) tree[i + r] = 1; for(int i = r - 1; i; --i) tree[i] = tree[2 * i] + tree[2 * i + 1]; gen(n, k, n * (n - 1) / 4); puts(""); }
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 111 112 113 114 115 116 117 | #include <bits/stdc++.h> using namespace std; #define int long long using ll = long long; const ll inf = 2e18; const int maxN = 1 << 18; vector<ll> _cnt[maxN]; // vector<ll> _sums[maxN]; ll get(ll n, ll k) { k = min(k, n * (n - 1) / 2 - k); if(k < 0) return 0; if(n == 1) return k == 0; assert(k >= 0); if(_cnt[n].size() <= k) return inf; return _cnt[n][k]; } ll getsum(ll n, ll a, ll b) { a = max(a, 0LL); b = min(b, n * (n - 1) / 2); if(a > n * (n - 1) / 2) return 0; if(a > b) { printf("%lld %lld %lld\n", n, a, b); assert(a <= b); } if((b - a) > 40) return inf; ll res = 0; for(ll i = a; i <= b; ++i) res = min(inf, res + get(n, i)); return res; } ll count(int n, ll k) { // ll res = 0; // for(int in = 0; in < n; ++in) // res = min(get(n - 1, k - in, _cnt) + res, inf); // return res; return getsum(n - 1, k - n + 1, k); } const int r = 1 << 18; int tree[2 * r]; void print_kth(int k) { int x = 1; tree[x]--; while(x < r) { if(tree[2 * x] >= k) x *= 2; else { x = 2 * x + 1; k -= tree[x - 1]; } tree[x]--; } printf("%lld ", x - r); } void gen(ll n, ll k, ll inw) { if(n == 0) return; assert(inw <= n * (n - 1) / 2); // printf("n=%lld, k=%lld, inw=%lld\n", n, k, inw); ll min_b = max(0LL, inw - (n - 1) * (n - 2) / 2); ll a = min_b - 1, b = min(n - 1, inw), avg; while(b - a > 1) { avg = (a + b) / 2; // printf("%lld %lld\n", a, b); assert(avg >= 0); // printf("sum %lld..%lld=%lld\n", inw-avg, inw, getsum(n-1, inw-avg, avg)); if(getsum(n - 1, inw - avg, inw - min_b) < k) a = avg; else b = avg; } if(b) k -= getsum(n - 1, inw - b + 1, inw - min_b); assert(k > 0); print_kth(b + 1); // printf("!!! [b=%lld]\n", b); gen(n - 1, k, inw - b); } #undef int int main() { #define int long long ll n, k; scanf("%lld%lld", &n, &k); for(ll _n = 1; _n <= n; ++_n) for(ll x, sx = 0, _k = 0; _k <= _n * (_n - 1) / 2; ++_k) { x = count(_n, _k); if(x != inf) { _cnt[_n].push_back(x); // if(_k) sx = _sums[_n].back(); // _sums[_n].push_back(min(inf, sx + x)); } else break; } if((n * (n - 1)) & 3 || count(n, n * (n - 1) / 4) < k) { puts("NIE"); return 0; } puts("TAK"); for(int i = 1; i <= n; ++i) tree[i + r] = 1; for(int i = r - 1; i; --i) tree[i] = tree[2 * i] + tree[2 * i + 1]; gen(n, k, n * (n - 1) / 4); puts(""); } |