Cod sursa(job #120784)

Utilizator bogdan2412Bogdan-Cristian Tataroiu bogdan2412 Data 6 ianuarie 2008 17:00:23
Problema NKPerm Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.26 kb
#include <cstdio>
#include <map>

using namespace std;

map< pair<int, int>, int > M;

const int MAXN = 32;
const int MAXK = 8;
const long long MAX = 1LL << 55;

int N, K, T;
int v[MAXK], left[MAXN];

inline int codif( int v[] )
{
	int rez = 0;
	for (int i = 0; i <= K; i++)
		rez = rez * (N + 1) + v[i];
	return rez;
}

inline void decodif( int val, int v[] )
{
	for (int i = K; i >= 0; i--)
		v[i] = val % (N + 1),
		val /= (N + 1);
}

inline long long get( int st, int last )
{
	if (M.find( make_pair(st, last) ) != M.end())
		return M[ make_pair(st, last) ];
	
	long long Rez = 0; int v[MAXK];
	decodif( st, v );
	for (int i = 1; i <= K; i++)
	{
		if (v[i] == 0) continue;
		v[i]--; v[i - 1]++;
		
		Rez += (v[i] + (last != i)) * get( codif(v), i - 1 );
		if (Rez > MAX)
		{
			Rez = MAX;
			break;
		}

		v[i]++; v[i - 1]--;
	}

	M.insert( make_pair( make_pair(st, last), Rez ) );

	return Rez;
}

int main()
{
	freopen("nkperm.in", "rt", stdin);
	freopen("nkperm.out", "wt", stdout);

	scanf("%d %d %d", &N, &K, &T);
	memset( v, 0, sizeof(v) );
	v[0] = N;
	M[ make_pair( codif(v) , 0 ) ] = 1;

	v[0] = 0;
	v[K] = N;
	get( codif(v), -1 );
	
	for (; T; T--)
	{
		char c;
		scanf(" %c", &c);
		for (int i = 0; i < N; i++)
			left[i] = K;
		memset( v, 0, sizeof(v) );
		v[K] = N;
			
		if (c == 'A')
		{
			long long Nr = 0;

			int last = -1;
			for (int i = 0; i < N * K; i++)
			{
				int val;
				scanf("%d", &val);
				val--;

				for (int a = 0; a < val; a++)
				{
					if (left[a] == 0 || a == last) continue;

					v[ left[a] ]--; v[ left[a] - 1 ]++;
					Nr += M[ make_pair( codif(v), left[a] - 1 ) ];
					v[ left[a] ]++; v[ left[a] - 1 ]--;
				}

				v[ left[ val ] ]--; v[ left[ val ] - 1 ]++;
				left[ val ]--; last = val;
			}
			printf("%lld\n", Nr + 1);
		}
		if (c == 'B')
		{
			long long Nr;
			scanf("%lld", &Nr);

			int last = -1;
			for (int step = 1; step <= N * K; step++)
				for (int k = 0; k < N; k++)
				{
					if (k == last || left[k] == 0) continue;
				
					v[ left[k] ]--; v[ left[k] - 1 ]++;
					if (M[ make_pair( codif(v), left[k] - 1 ) ] < Nr)
						Nr -= M[ make_pair( codif(v), left[k] - 1 ) ];
					else
					{
						printf("%d ", k + 1);
						last = k; left[k]--;
						break;
					}
					v[ left[k] ]++; v[ left[k] - 1 ]--;
				}
			printf("\n");
		}
	}

	return 0;
}