#include <cstdio> #include <iostream> #include <vector> using namespace std; const int kN = 1 << 18; class Tree { public: Tree() : v_(2 * kN) {} void Add(int i, const int delta) { i += kN; while (i) { v_[i] += delta; i /= 2; } } int Smallest(int k) const { int i = 1; while (i < kN) { i <<= 1; if (k >= v_[i]) k -= v_[i++]; } // cerr << i << endl; return i - kN; } private: vector<int> v_; }; const long long kInfinity = 1000LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL; const int kMaxN = 250000; const int kSumCount = 106; vector<vector<long long> > d(kMaxN + 1, vector<long long>(kSumCount)); void Precalc() { d[0][0] = 1; for (int i = 0; i < kMaxN; ++i) { bool is_infinity = false; long long s = 0; // printf("%d:", i + 1); for (int j = 0; j < kSumCount; ++j) { const long long old_s = s; s += d[i][j]; if (j > i) s -= d[i][j - i - 1]; if (is_infinity) { if (old_s >= kInfinity && s < kInfinity && s >= 0) is_infinity = false; } else { if (old_s >= 0 && old_s < kInfinity && s >= kInfinity) is_infinity = true; } d[i + 1][j] = is_infinity ? kInfinity : s; // if (d[i + 1][j] != 0) printf(" %lld", d[i + 1][j]); } // printf("\n"); } } long long GetMaxInversions(const long long n) { return (n * (n - 1)) / 2; } long long GetWays(const long long i, long long j) { // cerr << "GetWays " << i << " " << j << endl; if (j < kSumCount) return d[i][j]; j = GetMaxInversions(i) - j; if (j < 0) return 0; if (j < kSumCount) return d[i][j]; return kInfinity; } void Solve(const int n, long long k) { const long long total = GetMaxInversions(n); if (total % 2 == 1) { printf("NIE\n"); return; } long long desired = total / 2; if (k > GetWays(n, desired)) { printf("NIE\n"); return; } printf("TAK\n"); Tree t; for (int i = 0; i < n; ++i) t.Add(i + 1, 1); for (int i = 1; i < n; ++i) { int j = max(0LL, desired - GetMaxInversions(n - i)); desired -= j; // cerr << "step " << i << endl; while (k > GetWays(n - i, desired)) { // cerr << "!" << endl; k -= GetWays(n - i, desired); ++j; --desired; } // cerr << "after while" << endl; // cerr << j << "th" << endl; j = t.Smallest(j); // cerr << j << endl; printf("%d ", j); t.Add(j, -1); // cerr << "updated" << endl; } printf("%d\n", t.Smallest(0)); } int main() { Precalc(); int n; long long k; scanf("%d%lld", &n, &k); Solve(n, k); 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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | #include <cstdio> #include <iostream> #include <vector> using namespace std; const int kN = 1 << 18; class Tree { public: Tree() : v_(2 * kN) {} void Add(int i, const int delta) { i += kN; while (i) { v_[i] += delta; i /= 2; } } int Smallest(int k) const { int i = 1; while (i < kN) { i <<= 1; if (k >= v_[i]) k -= v_[i++]; } // cerr << i << endl; return i - kN; } private: vector<int> v_; }; const long long kInfinity = 1000LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL; const int kMaxN = 250000; const int kSumCount = 106; vector<vector<long long> > d(kMaxN + 1, vector<long long>(kSumCount)); void Precalc() { d[0][0] = 1; for (int i = 0; i < kMaxN; ++i) { bool is_infinity = false; long long s = 0; // printf("%d:", i + 1); for (int j = 0; j < kSumCount; ++j) { const long long old_s = s; s += d[i][j]; if (j > i) s -= d[i][j - i - 1]; if (is_infinity) { if (old_s >= kInfinity && s < kInfinity && s >= 0) is_infinity = false; } else { if (old_s >= 0 && old_s < kInfinity && s >= kInfinity) is_infinity = true; } d[i + 1][j] = is_infinity ? kInfinity : s; // if (d[i + 1][j] != 0) printf(" %lld", d[i + 1][j]); } // printf("\n"); } } long long GetMaxInversions(const long long n) { return (n * (n - 1)) / 2; } long long GetWays(const long long i, long long j) { // cerr << "GetWays " << i << " " << j << endl; if (j < kSumCount) return d[i][j]; j = GetMaxInversions(i) - j; if (j < 0) return 0; if (j < kSumCount) return d[i][j]; return kInfinity; } void Solve(const int n, long long k) { const long long total = GetMaxInversions(n); if (total % 2 == 1) { printf("NIE\n"); return; } long long desired = total / 2; if (k > GetWays(n, desired)) { printf("NIE\n"); return; } printf("TAK\n"); Tree t; for (int i = 0; i < n; ++i) t.Add(i + 1, 1); for (int i = 1; i < n; ++i) { int j = max(0LL, desired - GetMaxInversions(n - i)); desired -= j; // cerr << "step " << i << endl; while (k > GetWays(n - i, desired)) { // cerr << "!" << endl; k -= GetWays(n - i, desired); ++j; --desired; } // cerr << "after while" << endl; // cerr << j << "th" << endl; j = t.Smallest(j); // cerr << j << endl; printf("%d ", j); t.Add(j, -1); // cerr << "updated" << endl; } printf("%d\n", t.Smallest(0)); } int main() { Precalc(); int n; long long k; scanf("%d%lld", &n, &k); Solve(n, k); return 0; } |