Cod sursa(job #781169)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 23 august 2012 20:48:04
Problema NKPerm Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.17 kb
#include <cstdio>
#include <cstring>
#include <map>

using namespace std;

typedef long long LL;

const int MaxN = 25;
const int MaxK = 7;
const int Base = 21;
const LL oo = 1LL<<55;

map<int, LL> H;
int N, K;

inline int Encode(int Freq[], int Last) {
    int BasePow = 1, Conf = 0;
    for (int i = 0; i <= K; ++i) {
        Conf += BasePow*Freq[i];
        BasePow *= Base;
    }
    Conf += BasePow*Last;
    return Conf;
}

inline void Decode(int Conf, int Freq[], int &Last) {
    int BasePow = 1;
    for (int i = 0; i <= K; ++i) {
        Freq[i] = (Conf/BasePow)%Base;
        BasePow *= Base;
    }
    Last = (Conf/BasePow)%Base;
}

LL Solve(int Conf) {
    if (H.find(Conf) != H.end())
        return H[Conf];

    int Freq[MaxK], Last;
    Decode(Conf, Freq, Last);
    if (Freq[K] == N)
        return 1;

    LL Result = 0;
    for (int i = 0; i < K; ++i) {
        if (!Freq[i])
            continue;

        int Factor = Freq[i] - (i == Last);
        --Freq[i], ++Freq[i+1];
        Result += Factor*Solve(Encode(Freq, i+1));
        ++Freq[i], --Freq[i+1];

        if (Result >= oo) {
            Result = oo;
            break;
        }
    }
    H[Conf] = Result;
    return Result;
}

LL CountP(int P[]) {
    LL Result = 1;
    int Elements[MaxN], Last = 0;
    memset(Elements, 0, sizeof(Elements));

    for (int i = 0; i < N*K; ++i) {
        for (int j = 1; j < P[i]; ++j) {
            if (Elements[j] == K || j == Last)
                continue;

            ++Elements[j];

            int Freq[MaxK]; memset(Freq, 0, sizeof(Freq));
            for (int k = 1; k <= N; ++k)
                ++Freq[Elements[k]];
            Result += Solve(Encode(Freq, Elements[j]));

            --Elements[j];
        }
        ++Elements[P[i]], Last = P[i];
    }
    return Result;
}

void GetP(LL Index, int P[]) {
    int Elements[MaxN], Last = 0;
    memset(Elements, 0, sizeof(Elements));

    for (int i = 0; i < N*K; ++i) {
        for (P[i] = 1; P[i] <= N; ++P[i]) {
            if (Elements[P[i]] == K || P[i] == Last)
                continue;

            ++Elements[P[i]];

            int Freq[MaxK]; memset(Freq, 0, sizeof(Freq));
            for (int k = 1; k <= N; ++k)
                ++Freq[Elements[k]];
            int NPerm = Solve(Encode(Freq, Elements[P[i]]));

            --Elements[P[i]];

            if (Index <= NPerm)
                break;
            Index -= NPerm;
        }
        ++Elements[P[i]], Last = P[i];
    }
}

int main() {
    freopen("nkperm.in", "r", stdin);
    freopen("nkperm.out", "w", stdout);
    int T; scanf("%d %d %d", &N, &K, &T);
    for (; T; --T) {
        char Type; scanf("\n%c", &Type);
        if (Type == 'A') {
            int P[MaxN*MaxK];
            for (int i = 0; i < N*K; ++i)
                scanf("%d", &P[i]);
            printf("%lld\n", CountP(P));
        }
        else {
            LL Index; scanf("%lld", &Index);
            int P[MaxN*MaxK];
            GetP(Index, P);
            for (int i = 0; i < N*K; ++i)
                printf("%d ", P[i]);
            printf("\n");
        }
    }
    return 0;
}