Cod sursa(job #324986)

Utilizator Magnuscont cu nume gresit sau fals Magnus Data 18 iunie 2009 14:03:07
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.94 kb
#include <cstdio>   
#include <map>   
using namespace std;   
  
const int N = 20;   
const int BASE = N+1;   
const int K = 8;   
const long long REZ = ((long long)1) << 55;   
  
int n,k,t;   
map<int, long long> m;   
  
int code ( int f[], int last ) {   
    int pw = 1, rez = 0;   
    for (int i = 0; i <= k; ++i, pw *= BASE) rez += pw*f[i];   
    rez += pw*last;   
    return rez;   
}   
  
void decode ( int code, int f[], int &last ) {   
    int pw = 1;   
    for (int i = 0; i <= k; ++i, pw *= BASE) f[i] = (code/pw) % BASE;   
    last = (code/pw) % BASE;   
}   
  
long long count ( int conf ) {   
    if (m.find(conf) != m.end())   
        return m[conf];   
    int f[K], last;   
    decode(conf,f,last);   
    if (f[0] == n) return 1;   
    long long rez = 0;   
    for (int i = 1; i <= k; ++i) {   
        if (f[i] != 0) {   
            --f[i]; ++f[i-1];   
            rez += (f[i] + (i != last)) * count(code(f,i-1));   
            if (rez > REZ) {   
                rez = REZ;   
                break;   
            }   
            ++f[i]; --f[i-1];   
        }   
    }   
    m[conf] = rez;   
    return rez;   
}   
  
void a() {   
    int ap[N];   
    long long rez = 1;   
    int last = -1, x;   
    for (int i = 0; i < n; ++i) ap[i] = k;   
    for (int i = 0; i < n*k; ++i) {   
        scanf("%d",&x);   
        --x;   
        for (int j = 0; j < x; ++j) {   
            if (ap[j] > 0 && j != last) {   
                --ap[j];   
                int f[K];   
                memset(f,0,sizeof(f));   
                for (int t = 0; t < n; ++t) ++f[ap[t]];   
                rez += count(code(f,ap[j]));   
                ++ap[j];   
            }   
        }   
        --ap[x];   
        last = x;   
    }   
    printf("%lld\n",rez);   
}   
  
void b() {   
    int ap[N];   
    int last = -1;   
    long long x;   
    scanf("%lld",&x);   
    for (int i = 0; i < n; ++i) ap[i] = k;   
    for (int i = 0; i < n*k; ++i) {   
        int j;   
        long long s = 0;   
        for (j = 0; j < n; ++j) {   
            if (ap[j] > 0 && j != last) {   
                --ap[j];   
                int f[K];   
                memset(f,0,sizeof(f));   
                for (int t = 0; t < n; ++t) ++f[ap[t]];   
                long long y = count(code(f,ap[j]));   
                ++ap[j];   
                if (s + y >= x) break;   
                s += y;   
            }   
        }   
        x -= s;   
        --ap[j];   
        printf("%d ",j+1);   
        last = j;   
    }   
    printf("\n");   
}   
  
int main() {   
    freopen("nkperm.in","rt",stdin);   
    freopen("nkperm.out","wt",stdout);   
    scanf("%d %d %d",&n,&k,&t);   
    for (int i = 0; i < t; ++i) {   
        char cmd;   
        scanf(" %c ",&cmd);   
        if (cmd == 'A')   
            a(); else   
            b();   
    }   
}