Cod sursa(job #2437456)

Utilizator Ruxandra985Nanu Ruxandra Laura Ruxandra985 Data 9 iulie 2019 16:40:04
Problema NKPerm Scor 30
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.95 kb
#include <cstdio>
#include <map>
#define BASE 37
#define MOD 1000000007

using namespace std;
int n,k;
long long INF=36028797018963968;
map <long long , long long> mp[6];
int b[30],v[200],w[200];
inline long long modulo (long long cod){
    if (cod > MOD)
        return cod - MOD;
    if (cod < 0)
        return cod + MOD;
    return cod;
}
long long back (int nr[6] , int fqlast , long long cod){
    int i;
    long long sol = 0,sp;
    /// stii deja ca ai un prefix valid

    if (mp[fqlast][ cod ] != 0)
        return mp[fqlast][ cod ];
    if (nr[k] == n)
        return 1;
    for (i=0;i<k;i++){
        if (nr[i]){
            nr[i]--;
            nr[i+1]++;
            cod = ((cod - b[i] + b[i+1])%MOD + MOD )%MOD;
            if (i == fqlast){
                sp = (long long)nr[i] * back(nr,i+1,cod);
            }
            else {
                sp = (long long)(nr[i]+1) * back(nr,i+1,cod);
            }

            if ( sol > INF - sp){

                mp[fqlast][ cod ] = INF;
                return INF;

            }
            else sol += sp;

            nr[i]++;
            nr[i+1]--;
            cod = ((cod + b[i] - b[i+1])%MOD + MOD)%MOD;
        }
    }
    mp[fqlast][ cod ] = sol;
    return sol;
}
int solve_a (){
    int i,j;
    long long cod = 0 , ca = 0;
    long long sol = 0;
    int apar[30],nr[6];
    for (i=1;i<=n;i++)
        apar[i] = 0;

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

    for (i=1;i<=n*k;i++){
        for (j=1;j<v[i];j++){
            if (j!=w[i-1] && apar[j] + 1 <=k){
                w[i] = j;
                ca = cod;
                cod = ((cod - b[apar[j]] + b[apar[j] + 1])%MOD + MOD)%MOD;
                apar[j]++;
                nr[apar[j]-1] --;
                nr [apar[j]]++;
                sol = sol + back (nr , apar[j], cod);
                cod = ca;
                nr[apar[j]-1] ++;
                nr [apar[j]]--;
                apar[j]--;
            }
        }
        w[i] = v[i];
        cod = ((cod - b[apar[j]] + b[apar[j] + 1])%MOD + MOD)%MOD;
        apar[j]++;
        nr[apar[j]-1] --;
        nr[apar[j]]++;
    }
    return sol;
}
void solve_b (long long x){
    int i,j;
    long long cod = 0 , ca;
    long long p;
    int apar[30],nr[6];
    for (i=1;i<=n;i++)
        apar[i] = 0;

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

    for (i=1;i<=n*k;i++){
        for (j=1;j<=n;j++){
            if (j!=w[i-1] && apar[j] + 1 <=k){
                w[i] = j;
                ca = cod;
                cod = ((cod - b[apar[j]] + b[apar[j] + 1])%MOD + MOD)%MOD;
                apar[j]++;
                nr[apar[j]-1] --;
                nr [apar[j]]++;
                p = back(nr, apar[j] , cod);
                if (x - p <= 0){
                    w[i] = j;
                    break;
                }
                else{
                    x-=p;
                    cod = ca;
                    nr[apar[j]-1] ++;
                    nr [apar[j]]--;
                    apar[j]--;
                }
            }
        }
        v[i] = w[i];
        //printf ("%d ",v[i]);
    }
}
int main()
{
    FILE *fin = fopen ("nkperm.in","r");
    FILE *fout = fopen ("nkperm.out","w");
    int i,t;
    long long x;
    char c;
    fscanf (fin,"%d%d",&n,&k);
    /// precalculari

    b[0] = 1;
    for (i=1;i<=n;i++)
        b[i] = ((long long)b[i-1] * BASE)%MOD;

    fscanf (fin,"%d\n",&t);
    for (;t;t--){
        c=fgetc (fin);
        if (c=='A'){
            for (i=1;i<=n*k;i++){
                fscanf (fin,"%d",&v[i]);
            }
            fgetc (fin);
            fprintf (fout,"%lld\n",solve_a() + 1);
        }
        else {
            fscanf (fin,"%lld\n",&x);
            solve_b(x);
            for (i=1;i<=n*k;i++)
                fprintf (fout,"%d ",v[i]);
            fprintf (fout,"\n");
        }
    }
    return 0;
}