Cod sursa(job #2632415)

Utilizator giotoPopescu Ioan gioto Data 3 iulie 2020 11:22:59
Problema NKPerm Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.4 kb
#include <bits/stdc++.h>
using namespace std;

const long long MAX = 1LL << 55;

int n, k, t;
unordered_map <int, long long> mem;

int bagaHash(vector <int> &freq, int last) {
    int Hash = 0;
    for (int i = 0; i < k ; ++i)
        Hash = Hash * n + (freq[i] + 1);
    Hash = Hash * n + last;
    return Hash;
}

long long get_nr(vector <int> &freq, int last) {
    int Hash = bagaHash(freq, last);
    if (mem.count(Hash)) return mem[Hash];

    if (freq[k] == n) return 1;

    long long ans = 0;
    for (int i = 0; i < k ; ++i) {
        if (freq[i]) {
            --freq[i];
            ++freq[i + 1];

            if (i == last) {
                if (freq[i] > 0) ans = ans + 1LL * freq[i] * get_nr(freq, i + 1);
            }
            else ans = ans + 1LL * (freq[i] + 1) * get_nr(freq, i + 1);

            ++freq[i];
            --freq[i + 1];

            if (ans >= MAX) {ans = MAX; break ;}
        }
    }

    mem[Hash] = ans;
    return ans;
}

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

    scanf("%d%d%d\n", &n, &k, &t);

    char tip;
    long long cnt;

    while (t--) {
        scanf("%c", &tip);
        if (tip == 'A') {
            cnt = 0;

            vector <int> ap(n, 0);
            vector <int> freq(k + 1, 0);

            freq[0] = n;

            int x, last = -1;
            long long ans = 1;
            for (int i = 1; i <= n * k ; ++i) {
                scanf("%d", &x);
                --x;
                for (int j = 0; j < x ; ++j) {
                    if (ap[j] < k && last != j) {
                        --freq[ap[j]];
                        ++ap[j];
                        ++freq[ap[j]];

                        if (ap[j] - 1 == last) {
                            ans = ans + get_nr(freq, ap[j]);
                        }
                        else ans = ans + get_nr(freq, ap[j]);

                        --freq[ap[j]];
                        --ap[j];
                        ++freq[ap[j]];
                    }
                }
                --freq[ap[x]];
                ++ap[x];
                last = x;
                ++freq[ap[x]];
            }

            printf("%lld", ans);
        }
        else {
            scanf("%lld", &cnt);

            vector <int> ap(n + 1, 0);
            vector <int> freq(k + 1, 0);
            vector <int> ans(n * k + 1, 0);
            freq[0] = n;

            int last = -1;
            for (int i = 1; i <= n * k ; ++i) {
                for (int j = 0; j < n ; ++j) {
                    if (ap[j] >= k || j == last) continue ;
                    --freq[ap[j]];
                    ++ap[j];
                    ++freq[ap[j]];

                    long long aux = get_nr(freq, ap[j]);
                    if (cnt <= aux) {
                        last = j;
                        ans[i] = j + 1;
                        break ;
                    }
                    else {
                        cnt -= aux;
                        --freq[ap[j]];
                        --ap[j];
                        ++freq[ap[j]];
                    }
                }
            }

            for (int i = 1; i <= n * k ; ++i)
                printf("%d ", ans[i]);
        }

        printf("\n");
        scanf("\n");
    }

    return 0;
}