Cod sursa(job #1850611)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 18 ianuarie 2017 19:46:28
Problema NKPerm Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.68 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<<56LL;
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 && rez < inf; 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) 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; st <= n*k; st++)
    {
        c[st] = spot(1, c[st-1]);
        state[c[st]]--;
        for (i64 v = ind-cnt(c[st]); v > 0; v = ind - cnt(c[st]))
        {
            ind = v;
            state[c[st]]++;
            c[st] = spot(c[st]+1, c[st-1]);
            state[c[st]]--;
        }
    }
}

i64 guessIndex()
{
    i64 rez = 0 ;
    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+1;
}

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+1; i++)
        put[i] = (n+1) * 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;
}