Cod sursa(job #111094)

Utilizator MariusMarius Stroe Marius Data 28 noiembrie 2007 17:16:52
Problema NKPerm Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.46 kb
#include <cstdio>
#include <map>

using namespace std;

const char iname[] = "nkperm.in";
const char oname[] = "nkperm.out";

typedef long long i64;

#define MAXNK  101
#define MAXN   21
#define MAXK   6

map <int, i64> M;


inline int getState(int cate[], int ultim, int N, int K)
{
	int state = 0;

	for (int i = 0; i <= K; ++ i)
		state = state * (N + 1) + cate[i];
	state = state * (N + 1) + ultim;

	return state;
}


i64 numara(int cate[], int ultim, int N, int K)
{
	int state = getState(cate, ultim, N, K);
	i64 rez = 0;
	
	if (M[state])
		return M[state];
	if (cate[K] == N)
		return M[state] = 1;

	for (int i = 0; i < K; ++ i) if (cate[i] != 0)
	{
		cate[i] --;
		cate[i + 1] ++;
		if (i == ultim)
			rez += cate[i] * numara(cate, i + 1, N, K);
		else
			rez += (cate[i] + 1) * numara(cate, i + 1, N, K);
		cate[i + 1] --;
		cate[i] ++;
	}
	if (M[state] > 1 << 55LL)
		M[state] = 1 << 55LL;
	return M[state] = rez;
}

i64 f(int P[], int N, int K)
{
	int aparitii[MAXN] = {0};
	int cate[MAXK] = {N};
	i64 rez = 1;

	for (int i = 0; i < N*K; ++ i)
	{
		for (int j = 1; j < P[i]; ++ j) 
			if (aparitii[j] < K) if (!i || (i && j != P[i - 1])) 
			{
				cate[aparitii[j]] --;
				cate[aparitii[j] + 1] ++;
				rez += numara(cate, aparitii[j] + 1, N, K);
				cate[aparitii[j] + 1] --;
				cate[aparitii[j]] ++;
			}
		cate[aparitii[P[i]]] --;
		aparitii[P[i]] ++;
		cate[aparitii[P[i]]] ++;
	}
	return rez;
}

void g(i64 X, int N, int K)
{
	int aparitii[MAXN] = {0};	
	int cate[MAXK] = {N};
	int last = 0;
	i64 rez = 0;

	for (int i = 0; i < N*K; ++ i) 
	{
		for (int j = 1; j <= N; ++ j) 
			if (aparitii[j] < K) if (!i || (i && j != last))
			{
				cate[aparitii[j]] --;
				cate[aparitii[j] + 1] ++;
				if (rez + numara(cate, aparitii[j] + 1, N, K) >= X)
				{
					printf("%d ", j);
					aparitii[j] ++;
					last = j;
					break ;
				} else
					rez += numara(cate, aparitii[j] + 1, N, K);
				cate[aparitii[j] + 1] --;
				cate[aparitii[j]] ++;
			}
	}
	printf("\n");
}

int main(void)
{
	freopen(iname, "r", stdin);
	freopen(oname, "w", stdout);
	char ch;
	int N, K, T;
	i64 X;
	int P[MAXNK];

	scanf("%d %d %d\n", &N, &K, &T);
	for (; T > 0; -- T) 
	{
		scanf("%c", &ch);
		if (ch == 'A') {
			for (int i = 0; i < N*K; ++ i)
				scanf("%d", &P[i]);
			printf("%lld\n", f(P, N, K));
		} else {
			scanf("%lld", &X);
			g(X, N, K);
		}
		scanf("\n");
	}
	return 0;
}