Cod sursa(job #120329)

Utilizator peanutzAndrei Homorodean peanutz Data 4 ianuarie 2008 22:34:28
Problema NKPerm Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.21 kb
#include <stdio.h>
#include <string.h>
#include <map>
#include <vector>

using namespace std;

#define NMAX 22
const long long MAX = (1LL << 55);

int n, k, t;
short p[NMAX];
int until;
short aparitii[NMAX];
map< vector<short>, long long> h;
long long x;

long long numara(vector<short> v)
{
    if(h.find(v) != h.end()) return h[v];
    if(v[k] == n) return 1;
    int i;
    short ultim = v[k+1];
    long long aux, res = 0;

    for(i = 0; i < k; ++i)
        if(v[i])
        {
            --v[i];
            ++v[i+1];
            v[k+1] = i+1;
            if(ultim != i)
            {
                    aux = (long long)(v[i]+1) * numara(v);
                    //h[v] = aux;
                    res = (long long)res + aux;
            }
            else
             {
                    aux = (long long)v[i] * numara(v);
                    //h[v] = aux;
                    res = (long long)res + aux;
            }
            ++v[i];
            --v[i+1];
            
            if(res >= MAX) return MAX;
        }
    v[k+1] = ultim;
    h[v] = res;
    return res;
}
    
long long findA()
{
    long long res = 1;
    vector<short> v(k+2, 0);
    memset(aparitii, 0, sizeof(aparitii));
    v[0] = n;
    for(int i = 1, j; i <= until; ++i)
    {
        for(j = 1; j < p[i]; ++j)
            if(j != p[i-1] && aparitii[j] < k)
            {
                --v[ aparitii[j] ];
                ++v[ aparitii[j]+1 ];
                v[k+1] = aparitii[j]+1;
                res = (long long)res + numara(v);
                ++v[ aparitii[j] ];
                --v[ aparitii[j]+1 ];
            }
        --v[ aparitii[ p[i] ] ];
        ++aparitii[ p[i] ];
        ++v[ aparitii[ p[i] ] ];
    }
    return res;
}

void findB()
{
    vector<short> v(k+2, 0);
    long long aux, res = 0;
    memset(aparitii, 0, sizeof(aparitii));
    v[0] = n;

    for(int j, i = 1; i <= until; ++i)
    {
        for(j = 1; j <= n; ++j)
        {
            if(j != p[i-1] && aparitii[j] < k)
            {
                --v[ aparitii[j] ];
                ++v[ aparitii[j]+1 ];
                v[k+1] = aparitii[j]+1;
                aux = numara(v);
                ++v[ aparitii[j] ];
                --v[ aparitii[j]+1 ];
            
                if(res + aux >= x)
                {
                    p[i] = j;
                    j = n+1;
                }
                else res += aux;
            }
        }
        --v[ aparitii[p[i]] ];
        ++aparitii[p[i]];
        ++v[ aparitii[p[i]] ];
    }
    for(int i = 1; i <= until; ++i)
        printf("%d ", p[i]);
    printf("\n");
}
            
int main()
{
    freopen("nkperm.in", "r", stdin);
    freopen("nkperm.out", "w", stdout);
    
    scanf("%d %d %d\n", &n, &k, &t);
    until = n*k;
    char c;
    short i;
    while(t--)
    {
        scanf("%c ", &c);
        if(c == 'A')
        {
            for(i = 1; i <= until; ++i)
                scanf("%d", &p[i]);
            printf("%lld\n", (long long)findA());
        }
        else
        {
            scanf("%lld", &x);
            findB();
        }
        scanf("\n");
    }

    return 0;
}