#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; } |
English