Cod sursa(job #388866)

Utilizator andrei-alphaAndrei-Bogdan Antonescu andrei-alpha Data 31 ianuarie 2010 11:26:00
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.08 kb
#include <ext/hash_map>
#include <map>
#define ll long long
#define mp make_pair
#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);++(i))
#define oo (1LL<<55)

using namespace std;

int N,K,T,M;
map<int,ll> H;

inline void convert(char A[],int Alast,char B[],int &Blast)
{
	FOR(i,0,K) B[i] = 0;
	FOR(i,1,N) ++B[ A[i] ];
	Blast = A[Alast];
}

inline int code(char A[],int last)
{
	int rez(0);
	FOR(i,0,K) 
		rez = (rez * 21) + A[i];
	rez = (rez * 21) + last;
	return rez;
}

inline void remake(int Cfg,char B[],char &last)
{
	last = Cfg % 21;
	Cfg /= 21;
	for(int i = K;i >= 0;--i)
		B[i] = Cfg % 21,Cfg /= 21;
}

ll count(int Cfg)
{
	if(H.find(Cfg) != H.end() )
		return (ll)H[Cfg];
	char B[6]={0},last;
	remake(Cfg,B,last);
	if(B[K] == N)
		return (ll)(H[Cfg] = 1);
	
	ll rez = 0;
	FOR(i,0,K-1)
	{
		if(!B[i])
			continue;
		--B[i],++B[i+1];
        
		rez += (ll)((i == last) ? (ll)B[i] : (ll)(B[i]+1)) * (ll)count( code(B,i+1) );
        if(rez >= oo) 
		{ 
			rez = oo; 
			break;
		}
 
		++B[i],--B[i+1];
	}
	return (H[Cfg] = rez);
}

int main()
{
	freopen("nkperm.in","r",stdin);
	freopen("nkperm.out","w",stdout);
	
	scanf("%d%d%d",&N,&K,&T);
	M = N*K;
	
	ll nr,cnt;
	int last,x,poz;
	
	for(char ch;T-- && scanf(" %c",&ch);)
		if(ch == 'B')
		{
			scanf("%lld",&nr);
			
			char B[10]={0},A[32]={0};
			last = 0;
			
			FOR(i,1,N*K)
			{
				FOR(j,1,N)
				{
					if(j==last || A[j] == K)
						continue;
					
					++A[j];
					convert(A,j,B,poz);
					--A[j];
					
					cnt = count( code(B,poz) );
					if(cnt >= nr)
					{
						printf("%d ",(last = j));
						break;
					}
					else
						nr -= cnt;
				}
				++A[last];	
			}
			printf("\n");
		}
		else
		{
			char B[10]={0},A[32]={0};
			nr = last = 0;
			
			FOR(i,1,N*K)
			{
				scanf(" %d",&x);
				FOR(j,1,x-1)
				{
					if(j==last || A[j] == K)
						continue;
					
					++A[j];
					convert(A,j,B,poz);
					--A[j];

					nr += count( code(B,poz) );
				}
				++A[(last = x)];
			}
			printf("%lld\n",nr+1);
		}
	
	return 0;
}