Cod sursa(job #120196)

Utilizator devilkindSavin Tiberiu devilkind Data 4 ianuarie 2008 15:52:03
Problema NKPerm Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.74 kb
#include <stdio.h>
#include <vector>
#include <map>

using namespace std;

#define pb push_back
#define sz size()
#define mp make_pair
#define NMAX 102
#define lim (long long) 1 << 56


long int n,i,j,k,T,v[NMAX],ptr[NMAX],h[NMAX];
char s[500];
unsigned int nr;
long long x,rez,cnt;

map< pair<unsigned int,int> ,long long > dp,viz;


long long numara(unsigned int nr, int ult)
{
if (viz[ mp(nr,ult) ]) return dp[ mp(nr,ult) ];

if (nr==n*ptr[k]) return 1;

viz[ mp(nr,ult) ] = 1;


long int i,aux,ap[10];
long long rez=0;

memset(ap,0,sizeof(ap));
for (aux=nr,i=0;aux;aux/=(n+1),i++) ap[i]=aux%(n+1);

for (i=0;i<k;i++)
        {
        if (ap[i]==0) continue;
        aux=nr - ptr[i] + ptr[i+1];
        if (ult==i) rez=rez+numara(aux,i+1) * (ap[i]-1);
                else rez=rez+numara(aux,i+1) * ap[i];
        if (rez > lim ) {
                        dp[ mp(nr,ult) ] = lim;
                        return lim;
                        }
        aux=nr - ptr[i+1] + ptr[i];
        }
dp[ mp(nr,ult) ] = rez;
return rez;
}



void tip_A()
{
x=0;

for (i=2,j=1;s[i]!='\n';i++)
        if ( (s[i]>='0')&&(s[i]<='9') ) x=x*10+s[i]-'0';
                else {
                     v[j++]=x;
                     x=0;
                     }
v[n*k]=x;
nr=n;
rez=0;
memset(h,0,sizeof(h) );
for (i=1;i<=n*k;i++)
        {
        for (j=1;j<v[i];j++)
                {
                if (h[j]==k) continue;
                if (j==v[i-1]) continue;
                nr=nr - ptr[ h[j] ]+ptr[ h[j]+1 ];
                cnt=numara(nr,h[j]+1);
                nr=nr - ptr[ h[j]+1 ]+ptr[ h[j] ];
                rez=rez+cnt;
                }
        h[ v[i] ]++;
        nr=nr - ptr[ h[v[i]]-1 ] + ptr[ h[ v[i] ] ];
        }
printf("%lld\n",rez+1);
}



void tip_B()
{
x=0;
for (i=2;s[i]!='\n';i++)
        x=x*10+(long long) (s[i]-'0');

memset(h,0,sizeof(h));

nr=n;
int ok;
cnt=0;
memset(v,0,sizeof(v));
for (i=1;i<=n*k;i++)
        {
        for (j=1;;j++)
                {
                if ( (j==v[i-1])||(h[j]==k) ) continue;
                ok=0;
                nr=nr - ptr[ h[j] ] + ptr[ h[j]+1 ];                
                cnt=cnt+numara(nr,h[j]+1);
                if (cnt>=x) {cnt-=numara(nr,h[j]+1);ok=1;}
                nr=nr - ptr[ h[j]+1 ] + ptr[ h[j] ];
                if (ok) {v[i]=j;break;}
                }
        nr=nr - ptr[ h[ v[i] ] ] + ptr[ h[ v[i] ]+1 ];
        h[ v[i] ]++;
        }
        
for (i=1;i<=n*k;i++)
        printf("%ld ",v[i]);
printf("\n");
}

int main()
{
freopen("nkperm.in","r",stdin);
freopen("nkperm.out","w",stdout);

scanf("%ld %ld %ld\n",&n,&k,&T);

for (i=0,x=1;i<=k;i++,x*=(n+1) )
             ptr[i]=x;

for (;T;T--)
        {
        fgets(s,500,stdin);

        if (s[0]=='A') tip_A();
                else tip_B();
        }
return 0;
}