Cod sursa(job #678723)

Utilizator rootsroots1 roots Data 12 februarie 2012 12:06:02
Problema NKPerm Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.04 kb
#include <stdio.h>
#include <string.h>

#define maxN 21
#define maxK 6
#define maxn 101

#define mod 999983

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

int v[maxn];
int pre[maxn];
int num[maxN];

int N,K,n;

inline long long back(int v[],int num[],int x)
{
    long long ret=0;

    if(x>n) return 1;

    for(int i=1;i<=N;++i)
        if(i!=v[x-1]&&num[i]<K)
        {
            ++num[i];
            v[x]=i;
            ret+=back(v,num,x+1);
            --num[i];
        }

    return ret;
}

inline long long con(int v[])
{
    long long ret=0;
    int num[maxK];

    memset(num,0,sizeof(num));

    for(int i=1;i<=N;++i) ++num[v[i]];

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

    return ret;
}

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

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

int main()
{
    int T;
    char ch;
    long long cnt,sub,e,ok;

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

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

    n=N*K;

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

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

        if(ch=='A')
        {
            for(int i=1;i<=n;++i) scanf("%d%c",&v[i],&ch);

            cnt=1;
            memset(pre,0,sizeof(pre));
            memset(num,0,sizeof(num));

            for(int i=1;i<=n;++i)
            {
                for(int j=1;j<v[i];++j)
                    if(j!=v[i-1]&&num[j]<K)
                    {
                        pre[i]=j;
                        ++num[j];

                        e=con(num);
                        ok=find(e);

                        if(ok==-1)
                        {
                            ok=back(pre,num,i+1);
                            cnt+=ok;
                            add(e,ok);
                        }
                        else cnt+=ok;

                        --num[j];
                    }
                pre[i]=v[i];
                ++num[v[i]];
            }

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

            memset(v,0,sizeof(v));
            memset(num,0,sizeof(num));

            for(int i=1;i<=n;++i)
                for(int j=1;j<=N;++j)
                    if(j!=v[i-1]&&num[j]<K)
                    {
                        ++num[j];
                        v[i]=j;
                        sub=back(v,num,i+1);
                        --num[j];

                        if(sub>cnt)
                        {
                            v[i]=j;
                            ++num[v[i]];
                            break;
                        }
                        else cnt-=sub;
                    }

            for(int i=1;i<=n;++i) printf("%d ",v[i]);
            printf("\n");
        }
    }

    return 0;
}