Cod sursa(job #678917)

Utilizator rootsroots1 roots Data 12 februarie 2012 15:49:18
Problema NKPerm Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.68 kb
#include <stdio.h>
#include <string.h>

#define maxK 6
#define maxN 21

#define mod 999983

struct hash
{
    int nod;
    long long val;
    hash *link;
}*H[mod];

int N,K,NK;

int num[maxN];
int d[maxK];

inline void add(int nod,long long val)
{
    hash *h=new hash;
    h->nod=nod;
    h->val=val;
    h->link=H[nod%mod];
    H[nod%mod]=h;
}

inline long long find(int nod)
{
    for(hash *h=H[nod%mod];h;h=h->link)
        if(h->nod==nod) return h->val;
    return -1;
}

inline long long convert(int last)
{
    long long ret=0;

    for(int i=0;i<=K;++i)
        ret=ret*(N+1)+d[i];

    ret=ret*(N+1)+last;

    return ret;
}

inline long long back(int x)
{
    if(d[K]==N) return 1;

    long long e,f,ret=0;

    for(int i=0;i<K;++i)
        if(d[i])
        {
            --d[i];
            ++d[i+1];

            e=convert(i+1);
            f=find(e);

            if(f==-1)
            {
                f=back(i+1);
                if(f) add(e,f);
            }

            if(i==x) ret+=d[i]*f;
            else ret+=(d[i]+1)*f;

            --d[i+1];
            ++d[i];
        }

    return ret;
}

int main()
{
    int T,x,ax;
    char ch;
    long long cnt,e,f;

    freopen("nkperm.in","r",stdin);

    scanf("%d %d %d\n",&N,&K,&T);
    NK=N*K;

    freopen("nkperm.out","w",stdout);

    while(T--)
    {
        scanf("%c ",&ch);

        if(ch=='A')
        {
            cnt=0;
            ax=0;
            memset(num,0,sizeof(num));
            memset(d,0,sizeof(d));
            d[0]=N;

            for(int i=1;i<=NK;++i)
            {
                scanf("%d%c",&x,&ch);

                for(int j=1;j<x;++j)
                    if(ax!=j&&num[j]<K)
                    {
                        --d[num[j]++];
                        ++d[num[j]];

                        e=convert(num[j]);
                        f=find(e);

                        if(f==-1)
                        {
                            f=back(num[j]);
                            if(f) add(e,f);
                        }

                        cnt+=f;

                        --d[num[j]--];
                        ++d[num[j]];
                    }

                --d[num[x]++];
                ++d[num[x]];

                ax=x;
            }

            printf("%lld\n",cnt+1);
        }
        else
        {
            scanf("%lld\n",&cnt);
            --cnt;

            memset(num,0,sizeof(num));
            memset(d,0,sizeof(d));
            d[0]=N;
            ax=0;

            for(int ok=0,i=1;i<=NK;++i,ok=0)
            {
                for(int j=1;j<=N;++j)
                    if(ax!=j&&num[j]<K)
                    {
                        --d[num[j]++];
                        ++d[num[j]];

                        e=convert(num[j]);
                        f=find(e);

                        if(f==-1)
                        {
                            f=back(num[j]);
                            if(f) add(e,f);
                        }

                        if(f>cnt)
                        {
                            ax=j;
                            ok=1;
                            break;
                        }

                        cnt-=f;

                        --d[num[j]--];
                        ++d[num[j]];
                    }
                if(!ok)
                {
                    --d[num[N]++];
                    ++d[num[N]];
                    ax=N;
                }

                printf("%d ",ax);
            }
            printf("\n");
        }
    }

    return 0;
}