Cod sursa(job #1068930)

Utilizator geniucosOncescu Costin geniucos Data 28 decembrie 2013 23:10:38
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.32 kb
#include<cstdio>
#include<vector>
using namespace std;
int C,T,N,K,i,j,ap[23],a[109],b[107],pw[7];
char tip,U;
long long poz,h;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////precalculari
int lin,mod=666013;
long long INF=1LL<<55;
struct str
{
    int C;
    long long cnt;
    char u;
}acr;
str make_str(int C,long long cnt,char u)
{
    acr.C=C;
    acr.cnt=cnt;
    acr.u=u;
    return acr;
}
vector < str > v[666013];
vector < str >::iterator it;
int H(int Cate,char ultim){return (ultim+(ultim^786852)+(Cate^981759)+Cate)%mod;}
long long V(int C,char u)
{
    lin=H(C,u);
    for(it=v[lin].begin();it!=v[lin].end();it++)
        if(it->C==C&&it->u==u) return it->cnt;
    return -1;
}
long long CNT(int Cate,char ultim)
{
    long long ceva=V(Cate,ultim);
    if(ceva!=-1) return ceva;
    char cat[7];
    int i,aux=Cate;
    ceva=0;
    for(i=0;i<=K;i++)
    {
        cat[i]=aux%(N+2);
        aux/=N+2;
    }
    if(cat[K]==N) ceva=1;
    else
    {
        for(i=0;i<=K-1;i++)
            if(cat[i]>0)
            {
                Cate-=pw[i];
                Cate+=pw[i+1];
                if(i==ultim) ceva+=1LL*(cat[i]-1)*CNT(Cate,i+1);
                else ceva+=1LL*cat[i]*CNT(Cate,i+1);
                Cate-=pw[i+1];
                Cate+=pw[i];
                if(ceva>INF)
                {
                    ceva=INF;
                    break;;
                }
            }
    }
    v[H(Cate,ultim)].push_back(make_str(Cate,ceva,ultim));
    return ceva;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void calc(int &C,char &U,int l)
{
    int i,ap[23],cat[7];
    //////calculez configuratia pentru prefixul de lungime l
    for(i=1;i<=N;i++)
        ap[i]=0;
    for(i=1;i<=l;i++)
        ap[a[i]]++;
    for(i=0;i<=K;i++)
        cat[i]=0;
    for(i=1;i<=N;i++)
        cat[ap[i]]++;
    C=0;
    for(i=0;i<=K;i++)
        C+=pw[i]*cat[i];
    U=ap[a[l]];
}
int main()
{
freopen("nkperm.in","r",stdin);
freopen("nkperm.out","w",stdout);
scanf("%d",&N);
scanf("%d",&K);
scanf("%d\n",&T);
pw[0]=1;
for(i=1;i<=K;i++)
    pw[i]=pw[i-1]*(N+2);
while(T)
{
    T--;
    scanf("%c ",&tip);
    if(tip=='A')
    {
        poz=1;
        for(i=1;i<=N;i++)
            ap[i]=0;
        for(i=1;i<=N*K;i++)
        {
            scanf("%d",&b[i]);
            for(j=1;j<b[i];j++)
                if(j!=a[i-1]&&ap[j]<K)
                {
                    a[i]=j;
                    calc(C,U,i);
                    poz+=CNT(C,U);
                }
            a[i]=b[i];
            ap[a[i]]++;
        }
        printf("%lld\n",poz);
    }
    else
    {
        scanf("%lld",&poz);
        for(i=1;i<=N;i++)
            ap[i]=0;
        for(i=1;i<=N*K;i++)
        {
            for(j=1;j<=N;j++)
                if(ap[j]<K&&j!=a[i-1])
                {
                    a[i]=j;
                    calc(C,U,i);
                    h=CNT(C,U);
                    if(h>=poz) break;
                    poz-=h;
                }
            a[i]=j;
            ap[j]++;
            printf("%d ",j);
        }
        printf("\n");
    }
    scanf("\n");
}
return 0;
}