Cod sursa(job #110570)

Utilizator DITzoneCAdrian Diaconu DITzoneC Data 26 noiembrie 2007 23:07:01
Problema NKPerm Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.57 kb
#include <stdio.h>
#include <ext/hash_map>

using namespace __gnu_cxx;

#define VI vector <char>
#define FOR(i,s,d) for(i=(s);i<(d);++i)
#define pb push_back
#define INF ((ldouble)1<<55)
#define MASK 31
#define BAZA 5

typedef long long ldouble;

hash_map <int,ldouble> H;
int n,k,T,p[256],m;

inline int f(int x,int i,int j=-1)
{
	int z,y;
	if(j==-1) j=i*BAZA;
	z=(x>>j)&MASK; z^=z-1; y=x^(z<<j); 
	j-=BAZA;
	z=(x>>j)&MASK; z^=z+1; y=y^(z<<j);
	y=(y>>BAZA)<<BAZA; y|=i-1;
	return y;	
}

ldouble doit(int x)
{
	if(!(x>>BAZA))  return 1;
	ldouble aux=H[x],z;
	if(aux> 0) return aux;
	if(aux< 0) return 0;
	int i,l=x&MASK,j=BAZA;
	for(i=1;i<=k;++i,j+=BAZA)
	{
		z=((x>>j)&MASK)-(i==l);
		if(z<=0) continue;
		aux+=doit(f(x,i,j))*z;
		if(aux>INF) aux=INF;
	}
	if(aux>0) H[x]=aux;
	else H[x]=-1;
	return aux;		
}

int main()
{
	int ii,i,iii,l,j;
	char s[16];
	ldouble nr,aux;
	int x; 
	freopen("nkperm.in","r",stdin);
	freopen("nkperm.out","w",stdout);
	scanf("%d %d %d",&n,&k,&T);
	m=n*k;

	FOR(i,0,k) H[i]=1;
	doit((n<<(BAZA*k))|31);
	FOR(ii,0,T)
	{
		scanf("%s",s);
		if(s[0]=='B')
		{
			scanf("%lld",&nr);
			FOR(i,0,n) p[i]=k;x=(n<<(BAZA*k))|n;l=n;
			FOR(iii,0,m)
			{
				FOR(i,0,n) if(p[i]&&i!=l)
					if((aux=doit(f(x,p[i])))>=nr)
					{
						l=i; x=f(x,p[i]--);
						printf("%d ",i+1);
						break;
					}
					else
						nr-=aux;					
			}
			printf("\n");
		}
		else
		{
			nr=0;
			FOR(i,0,n) p[i]=k;x=(n<<(BAZA*k))|n;l=n;
			FOR(iii,0,m)
			{
				scanf("%d",&j);
				FOR(i,0,j-1) if(p[i]&&i!=l)
					nr+=doit(f(x,p[i]));
				l=i,x=f(x,p[i]--);
			}
			printf("%lld\n",nr+1);
		}
	}
	return 0;
}