Cod sursa(job #109978)

Utilizator wefgefAndrei Grigorean wefgef Data 25 noiembrie 2007 15:05:16
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.46 kb
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;

const long long Inf = ((long long)1) << 55;
const int Base = 21;
const int Kmax = 8;
const int Nmax = 32;

int N, K;
map<int, long long> H;

int Codifica(int Frec[], int First) {
	int pow = 1;
	int ret = 0;
	for (int i = 0; i <= K; ++i) {
		ret += pow * Frec[i];
		pow *= Base;
	}
	ret += pow * First;
	return ret;
}

void Decodifica(int Conf, int Frec[], int &First) {
	int pow = 1;
	for (int i = 1; i <= K+1; ++i) {
		Frec[i-1] = (Conf/pow) % Base;
		pow *= Base;
	}
	First = (Conf/pow) % Base;
}

long long Solve(int Conf) {
	if (H.find(Conf) != H.end()) return H[Conf];

	int Frec[Kmax], First;
	Decodifica(Conf, Frec, First);
	if (Frec[0] == N) return 1;

	long long ret = 0;
	for (int i = 1; i <= K; ++i) {
		if (!Frec[i]) continue;

		long long factor = Frec[i] - (i == First);

		Frec[i]--; Frec[i-1]++;
		int New_Conf = Codifica(Frec, i-1);

		ret += factor * Solve(New_Conf);
		if (ret >= Inf) { ret = Inf; break; }

		Frec[i]++; Frec[i-1]--;
	}
	H[Conf] = ret;
	return ret;
}

int main() {
	freopen("nkperm.in", "r", stdin);
	freopen("nkperm.out", "w", stdout);

	int T;
	for (scanf("%d %d %d", &N, &K, &T); T; --T) {
		char ch; scanf(" %c ", &ch);

		if (ch == 'A') {
			int Aparitii[Nmax];
			for (int i = 1; i <= N; ++i)
				Aparitii[i] = K;
			long long ret = 1;
			int last = 0;

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

				for (int j = 1; j < val; ++j) {
					if (!Aparitii[j]) continue;
					if (j == last) continue;

					--Aparitii[j];
					int Frec[Kmax]; memset(Frec, 0, sizeof(Frec));
					for (int k = 1; k <= N; ++k)
						++Frec[Aparitii[k]];
					
					ret += Solve(Codifica(Frec, Aparitii[j]));

					++Aparitii[j];
				}

				--Aparitii[val];
				last = val;
			}
			printf("%lld\n", ret);
		}
		else {
			long long Count; scanf("%lld", &Count);
			int last = 0;
			int Aparitii[Nmax];
			for (int i = 1; i <= N; ++i)
				Aparitii[i] = K;

			for (int i = 0; i < N*K; ++i) {
				int j;
				long long Scade = 0;

				for (j = 1; j <= N; ++j) {
					if (!Aparitii[j]) continue;
					if (j == last) continue;

					--Aparitii[j];
					int Frec[Kmax]; memset(Frec, 0, sizeof(Frec));
					for (int k = 1; k <= N; ++k)
						++Frec[Aparitii[k]];

					long long Nr = Solve(Codifica(Frec, Aparitii[j]));

					++Aparitii[j];

					if (Scade + Nr >= Count) break;
					Scade += Nr;
				}

				Count -= Scade;
				--Aparitii[j];
				printf("%d ", j);
				last = j;
			}
			printf("\n");
		}
	}
}