Cod sursa(job #979028)

Utilizator mitrutstrutMitrea Andrei Ionut mitrutstrut Data 31 iulie 2013 10:24:19
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.08 kb
#include <cstring>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <map>
   
using namespace std;
   
const int MAXN = 8;
   
int N, K, T;
int X[102], fr[22];
int power[22], fullbase;
map<int, long long> P;
long long number;
   
inline int getdigit(int num, int what)
{
    return (num / power[what]) % (N + 1);
}
long long getP(int num)
{
    if (num / MAXN == N * power[K]) return 1;
    if (P.find(num) != P.end()) return P[num];
       
    int last = num % MAXN, bitn = num / MAXN;
       
    long long resultnow = 0;
    for (int i = 0; i <= K - 1; ++i) // iau una cu frecventa i
    {
        if (getdigit(bitn, i) - (i == last) > 0)
            resultnow += (getdigit(bitn, i) - (i == last)) * getP((bitn - power[i] + power[i + 1]) * MAXN + i + 1);
        if (resultnow >= (1LL << 55))
        {
            resultnow = 1LL << 55;
            break;
        }
    }
       
    P[num] = resultnow;
    return resultnow;
}
   
int main()
{
    ifstream fin("nkperm.in");
    ofstream fout("nkperm.out");
       
    fin >> N >> K >> T;
       
    power[0] = 1;
    for (int i = 1; i <= K + 1; ++i)
        power[i] = power[i - 1] * (N + 1);
       
    for (int test = 1; test <= T; ++test)
    {
        char opt;
           
        fin >> opt;
        if (opt == 'A')
        {
            for (int i = 1; i <= N * K; ++i)
                fin >> X[i];
               
            memset(fr, 0, sizeof(fr));
               
            long long result = 1;
            for (int i = 1; i <= N * K; ++i)
            {
                int basenow = 0;
                for (int j = 1; j <= N; ++j)
                    basenow += power[fr[j]];
                   
                for (int j = 1; j < X[i]; ++j)
                    if (j != X[i - 1] && fr[j] < K)
                        result += getP((basenow - power[fr[j]] + power[fr[j] + 1]) * MAXN + (fr[j] + 1));
                   
                ++fr[X[i]];
            }
               
            fout << result << '\n';
        }
        else
        {
            fin >> number;
            --number;
               
            memset(fr, 0, sizeof(fr));
               
            int basenow = power[0] * N, last = -1;
            for (int i = 1; i <= N * K; ++i)
            {
                int j;
                for (j = 1; j <= N; ++j)
                    if (j != last && fr[j] < K)
                    {
                        if (getP((basenow - power[fr[j]] + power[fr[j] + 1]) * MAXN + (fr[j] + 1)) <= number)
                            number -= getP((basenow - power[fr[j]] + power[fr[j] + 1]) * MAXN + (fr[j] + 1));
                        else
                            break;
                    }
                   
                basenow -= power[fr[j]];
                basenow += power[fr[j] + 1];
                ++fr[j];
                   
                fout << j << ' ';
                last = j;
            }
               
            fout << '\n';
        }
    }
       
    fin.close();
    fout.close();
}