#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
long long n, k, x, inwersje;
long long pom[250005];
int ktory[250005];
int drzewo[525000];
int drz;
vector <long long> v[250005];
int main()
{
long long MAX = 1000000000000000000LL;
drz = 262144;
scanf("%lld%lld", &n, &k);
if (n % 4 > 1)
{
printf("NIE\n");
return 0;
}
v[0].push_back(1);
for (long long i = 0; i <= n; ++i) pom[i] = i * (i - 1) / 2;
for (long long i = 1; i <= n; ++i)
{
for (long long j = 0; j <= pom[i]; ++j)
{
x = 0;
for (long long k = 0; k < i && k <= j; ++k)
{
if (j - k <= pom[i - 1]) x += v[i - 1][j - k];
if (x > MAX) break;
}
if (x > MAX)
{
v[i].push_back(MAX + 1);
break;
}
v[i].push_back(x);
}
}
if (n <= 20 && v[n][n * (n - 1) / 4] < k)
{
printf("NIE\n");
return 0;
}
inwersje = pom[n] / 2;
printf("TAK\n");
for (int j = drz + 1; j <= drz + n; ++j) drzewo[j] = 1;
for (int j = drz - 1; j > 0; --j) drzewo[j] = drzewo[2 * j] + drzewo[2 * j + 1];
for (int i = n - 1; i >= 0; --i)
{
if (inwersje > pom[i])
{
ktory[i] = (int)(inwersje - pom[i]);
inwersje = pom[i];
}
while (ktory[i] < i)
{
if (inwersje == 0) break;
x = min(inwersje, pom[i] - inwersje);
if (v[i].size() <= x) break;
if (v[i][x] >= k) break;
inwersje--;
k -= v[i][x];
ktory[i]++;
}
ktory[i]++;
x = 1;
while (x < drz)
{
if (drzewo[2 * x] >= ktory[i]) x *= 2;
else
{
ktory[i] -= drzewo[2 * x];
x = 2 * x + 1;
}
}
printf("%d ", x - drz);
while (x > 0)
{
drzewo[x]--;
x /= 2;
}
}
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 | #include <iostream> #include <cstdio> #include <vector> #include <algorithm> using namespace std; long long n, k, x, inwersje; long long pom[250005]; int ktory[250005]; int drzewo[525000]; int drz; vector <long long> v[250005]; int main() { long long MAX = 1000000000000000000LL; drz = 262144; scanf("%lld%lld", &n, &k); if (n % 4 > 1) { printf("NIE\n"); return 0; } v[0].push_back(1); for (long long i = 0; i <= n; ++i) pom[i] = i * (i - 1) / 2; for (long long i = 1; i <= n; ++i) { for (long long j = 0; j <= pom[i]; ++j) { x = 0; for (long long k = 0; k < i && k <= j; ++k) { if (j - k <= pom[i - 1]) x += v[i - 1][j - k]; if (x > MAX) break; } if (x > MAX) { v[i].push_back(MAX + 1); break; } v[i].push_back(x); } } if (n <= 20 && v[n][n * (n - 1) / 4] < k) { printf("NIE\n"); return 0; } inwersje = pom[n] / 2; printf("TAK\n"); for (int j = drz + 1; j <= drz + n; ++j) drzewo[j] = 1; for (int j = drz - 1; j > 0; --j) drzewo[j] = drzewo[2 * j] + drzewo[2 * j + 1]; for (int i = n - 1; i >= 0; --i) { if (inwersje > pom[i]) { ktory[i] = (int)(inwersje - pom[i]); inwersje = pom[i]; } while (ktory[i] < i) { if (inwersje == 0) break; x = min(inwersje, pom[i] - inwersje); if (v[i].size() <= x) break; if (v[i][x] >= k) break; inwersje--; k -= v[i][x]; ktory[i]++; } ktory[i]++; x = 1; while (x < drz) { if (drzewo[2 * x] >= ktory[i]) x *= 2; else { ktory[i] -= drzewo[2 * x]; x = 2 * x + 1; } } printf("%d ", x - drz); while (x > 0) { drzewo[x]--; x /= 2; } } return 0; } |
English