Cod sursa(job #1703555)

Utilizator sucureiSucureiRobert sucurei Data 17 mai 2016 09:25:56
Problema NKPerm Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.58 kb
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
using namespace std;

#define mp make_pair
#define pb push_back
#define x first
#define y second
#define pii pair<int, int>
#define pdd pair<double, double>
#define pid pair<int, double>
#define pdi pair<double, int>
#define ppi pair<pair<int, int>, int>
#define forit(it, v) for(__typeof(v.begin()) it = v.begin(); it != v.end(); ++it)
#define sz(v) v.size()
#define del(it, v) v.erase(it)
#define db double
#define ll long long

const int INF = 0x3f3f3f3f;
const int MAX_N = 20;
const int MAX_M = 0;
const int MAX_L = 10;
const int B = 21;
const ll PT = ((ll)1) << 55;

int n, k, t;
map <int, ll> hash;
int f[MAX_N];

int make(int f[], int p)
{
    int pow = 1, ret = 0;

    for (int i = 0; i <= k; ++i, pow *= B)
        ret += pow * f[i];

    return ret + pow * p;
}

inline ll numara(int cf)
{
    if (hash.find(cf) != hash.end())
        return hash[cf];

    int h[MAX_L], p;

    int pow = 1;

    for (int i = 0; i <= k; ++i, pow *= B)
        h[i] = (cf / pow) % B;
    p = (cf / pow) % B;

    if (h[0] == n)
        return 1;

    ll ret = 0;

    for (int i = 1; i <= k; ++i)
        if (h[i])
        {
            --h[i];
            ++h[i - 1];

            ret += (h[i] + (i != p)) * numara(make(h, i - 1));

            if (ret > PT)
            {
                ret = PT;
                break;
            }

            ++h[i];
            --h[i-1];
        }

    return hash[cf] = ret;
}

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

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

    for (; t; --t)
    {
        char c;
        int d[MAX_L];

        scanf(" %c", &c);

        if (c == 'A')
        {
            ll sol = 1;
            int p = -1, nr;

            for (i = 0; i < n; ++i)
                f[i] = k;

            for (i = 0; i < n * k; ++i)
            {
                scanf("%d", &nr);
                --nr;

                for (j = 0; j < nr; ++j)
                    if (f[j] > 0 && j != p)
                    {
                        --f[j];

                        memset(d, 0, sizeof(d));

                        for (l = 0; l < n; ++l)
                            ++d[f[l]];

                        int q = make(d, f[j]);

                        sol += numara(q);
                        ++f[j];
                    }

                --f[nr];
                p = nr;
            }
            printf("%lld\n", sol);

        }
        else
        {
            int p = -1;
            ll nr;

            scanf("%lld", &nr);

            for (i = 0; i < n; ++i)
                f[i] = k;

            for (i = 0; i < n * k; ++i)
            {
                ll sol = 0;

                for (j = 0; j < n; ++j)
                    if (f[j] > 0 && j != p)
                    {
                        --f[j];

                        memset(d, 0, sizeof(d));

                        for (l = 0; l < n; ++l)
                            ++d[f[l]];

                        int q = make(d, f[j]);

                        ll z = numara(q);

                        ++f[j];

                        if (sol + z >= nr) break;
                        sol += z;
                    }

                nr -= sol;
                --f[j];
                p = j;

                printf("%d ", j + 1);
            }

            printf("\n");
        }
    }
}