Cod sursa(job #1850714)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 18 ianuarie 2017 20:50:26
Problema NKPerm Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.79 kb
#include <iostream>
#include <cstdio>
#include <unordered_map>
#define MAXN 23

using namespace std;

int sol[MAXN], giv[MAXN];
int n, k, t, state[MAXN], kate[7], put[6];

int spot(int loc, int nm)
{
    for (int i = loc; i <= n; i++)
        if (state[i] && i != nm)
            return i;
}

typedef long long i64;
const i64 inf = 1LL<<55LL;
unordered_map<int, i64> memo;

int buildFrom(int exc)
{
    int r = exc * put[k+1];
    for (int i = 0; i <= k; i++)
        r += kate[i]*put[i];
    return r;
}

i64 dinam(int exc)
{
    int g = buildFrom(exc);
    if (memo.find(g) != memo.end())
        return memo[g];
    if (kate[0] == n)
        return 1;
    i64 rez = 0;
    for (int i = 1; i <= k; i++)
        if (kate[i]) {
            kate[i]--;
            kate[i-1]++;
            rez += 1LL*(kate[i]+(i != exc)) * dinam(i-1);
            kate[i]++;
            kate[i-1]--;
            if (rez > inf)
                break;
        }
    if (rez > inf) rez = inf;
    memo[g] = rez;
    return rez;
}

i64 cnt(int exc)
{
    for (int i = 0; i <= k; i++)
        kate[i] = 0;
    for (int i = 1; i <= n; i++)
        kate[state[i]]++;
    return dinam(state[exc]);
}

void getSol(i64 ind, int c[MAXN])
{
    for (int i = 1; i <= n; i++)
        state[i] = k;
    for (int st = 1, i; st <= n*k; st++)
    {
        i64 sc = 0;
        for (i = 1; i <= n; i++)
            if (state[i] && i != c[st-1]) {
                state[i]--;
                i64 v = cnt(i);
                state[i]++;
                if (sc + v >= ind)
                    break;
                sc += v;
            }
        ind -= sc;
        state[i]--;
        c[st] = i;
    }
}

i64 guessIndex()
{
    i64 rez = 1 ;
    for (int i = 1; i <= n; i++)
        state[i] = k;
    for (int i = 1; i <= n*k; i++) {
        for (int j = 1; j < giv[i]; j++)
            if (state[j] && j != giv[i-1])
            {
                state[j]--;
                rez += cnt(j);
                state[j]++;
            }
        state[giv[i]]--;
    }
    return rez;
}

int main()
{
    freopen("nkperm.in", "r", stdin);
    freopen("nkperm.out", "w", stdout);

    scanf("%d %d %d", &n, &k, &t);
    put[0] = 1;
    for (int i = 1; i <= k+2; i++)
        put[i] = 21 * put[i-1];
    while (t--) {
        char tip;
        i64 ind;
        scanf(" %c", &tip);
        if (tip == 'A') {
            for (int i = 1; i <= n*k; i++)
                scanf("%d", &giv[i]);
            printf("%lld\n", guessIndex());
        }
        else if (tip == 'B') {
            scanf("%lld", &ind);
            getSol(ind, sol);
            for (int i = 1; i <= n*k; i++)
                printf("%d ", sol[i]);
            printf("\n");
        }
    }

    return 0;
}