Cod sursa(job #111631)

Utilizator ProstuStefan-Alexandru Filip Prostu Data 1 decembrie 2007 16:42:09
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.34 kb
#include <cstdio>
#include <map>

using namespace std;

typedef long long llong;

const int DEP = 5;
const int MASK = (1 << DEP) - 1;
const llong INF = 1LL << 55;
const int KMAX = 6;
const int NMAX = 32;

int N, K, T;
map <int, llong> DP;

void toState(int cnf, int cate[], int &l) {
	int i;

	for (i = K - 1; i >= 0; --i)
		cate[i] = cnf & MASK,
		cnf >>= DEP;
	l = cnf;
}

void fromState(int cate[], int l, int &cnf) {
	int i;

	cnf = l;
	for (i = 0; i < K; ++i)
		cnf = (cnf << DEP) | cate[i];
}

llong go(int cnf) {
	map <int, llong> :: iterator f;
	f = DP.find(cnf);
	if (f != DP.end())
		return f->second;
	
	int cate[KMAX], l, i, ncnf;
	bool notok = true;
	llong rez = 0;

	toState(cnf, cate, l);

	for (i = 0; i < K; ++i) {
		if (cate[i] == 0) continue;
		notok = false;

		--cate[i];
		++cate[i + 1];
		fromState(cate, i + 1, ncnf);

		rez += (cate[i] + (l == i ? 0 : 1)) * go(ncnf);

		if (rez >= INF)
			return DP[cnf] = INF;
	
		++cate[i];
		--cate[i + 1];
	}

	if (notok) return 1;

	return DP[cnf] = rez;
}

int main(void) {
	FILE *fin = fopen("nkperm.in", "rt");
	FILE *fout = fopen("nkperm.out", "wt");
	int cate[KMAX], V[NMAX];
	int i, j, u, cnf, l;
	llong rez, aux, X;
	char type;
	
	fscanf(fin, " %d %d %d", &N, &K, &T);

	while (T--) {
		fscanf(fin , " %c", &type);

		if (type == 'A') {

			memset(cate, 0x00, sizeof(cate));
			memset(V, 0x00, sizeof(V));
			cate[0] = N;
			rez = 1; u = 0;

			for (i = 0; i < N*K; ++i) {
				l = u;
				fscanf(fin, " %d", &u);

				for (j = 1; j < u; ++j) {
					if (V[j] == K || j == l) continue;

					--cate[V[j]];
					++cate[V[j] + 1];

					fromState(cate, V[j] + 1, cnf);
					rez += go(cnf);

					++cate[V[j]];
					--cate[V[j] + 1];
				}

				--cate[V[u]];
				++V[u];
				++cate[V[u]];


			}

			fprintf(fout, "%lld\n", rez);

		} else {
			fscanf(fin, " %lld", &X);

			memset(cate, 0x00, sizeof(cate));
			memset(V, 0x00, sizeof(V));
			cate[0] = N;
			rez = 0; l = 0;

			for (i = 0; i < N*K; ++i) {
				
				for (j = 1; j <= N; ++j) {
					if (V[j] == K || j == l) continue;

					--cate[ V[j] ];
					++cate[ V[j] + 1];

					fromState(cate, V[j] + 1, cnf);

					if (rez + (aux = go(cnf)) >= X)
						break;
					else
						rez += aux;
				
					++cate[ V[j] ];
					--cate[ V[j] + 1];
				}

				++V[j]; l = j;
				fprintf(fout, "%d ", j);
			}
			fprintf(fout, "\n");
		}
	}

	fclose(fin);
	fclose(fout);
	return 0;
}