Cod sursa(job #387617)

Utilizator andrei-alphaAndrei-Bogdan Antonescu andrei-alpha Data 28 ianuarie 2010 01:49:28
Problema NKPerm Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.76 kb
using namespace std;

#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)

int N,K,T,M;
map< pair< vector<char>,ll> , ll> H;
vector<char> B(21);

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

ll count(vector<char> A,int last)
{
	if(H.find( mp(A,last) ) != H.end() )
		return H[ mp(A,last) ];
	if(A[K] == N)
		return 1;
	
	ll rez = 0;
	FOR(i,0,K-1)
	{
		if(!A[i])
			continue;
		--A[i],++A[i+1];
        
		rez += ((i == last) ? A[i] : A[i]+1) * count(A,i+1);
        if(rez >= oo) 
		{ 
			rez = oo; 
			break;
		}
 
        ++A[i],--A[i+1];
	}
	return (H[ mp(A,last) ] = 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 A[21]={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);
					if( (cnt = count(B,poz)) >= nr)
					{
						printf("%d ",(last = j));
						--A[j];
						break;
					}
					else
						nr -= cnt;
					--A[j];
				}
				++A[last];	
			}
			printf("\n");
		}
		else
		{
			char A[21]={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);
					nr += count(B,poz);
					--A[j];
				}
				++A[(last = x)];
			}
			printf("%lld\n",nr+1);
		}
	
	return 0;
}