Cod sursa(job #253351)

Utilizator 630r63Ilinca George Mihai 630r63 Data 5 februarie 2009 18:17:58
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();  
}
}