Cod sursa(job #1726300)

Utilizator iordache.bogdanIordache Ioan-Bogdan iordache.bogdan Data 7 iulie 2016 18:27:39
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.51 kb
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <unordered_map>

using namespace std;

ifstream fin("nkperm.in");
ofstream fout("nkperm.out");

typedef long long ll;

const int dimn = 21;
const int dimk = 6;
const ll inf = (1LL << 55);

int n, k;
unordered_map<int, ll> memo;

int getHash(int fr[], int last) {

	int pow = 1, ret = 0;
	for (int i = 0; i <= k; ++i) {
		ret += pow * fr[i];
		pow *= dimn;
	}

	ret += pow * last;
	return ret;

}

void reverseHash(int hash, int fr[], int& last) {

	for (int i = 0; i <= k; ++i)
		fr[i] = hash % dimn, hash /= dimn;

	last = hash;

}

ll countNKperm(int hash) {

	if (memo.count(hash))
		return memo[hash];

	int fr[6], last;
	reverseHash(hash, fr, last);

	if (fr[0] == n) 
		return 1;

	ll ret = 0;
	for (int i = 1; i <= k; ++i) {

		if (!fr[i]) continue;

		fr[i]--; fr[i - 1]++;

		if (i != last)
			ret += (fr[i] + 1) * countNKperm(getHash(fr, i - 1));
		else
			ret += fr[i] * countNKperm(getHash(fr, i - 1));

		fr[i]++, fr[i - 1]--;

		if (ret >= inf)
			return memo[hash] = inf;

	}

	return memo[hash] = ret;

}

void solveA(void) {

	static int remain[dimn], fr[dimk];
	for (int i = 1; i <= n; ++i)
		remain[i] = k;

	ll ans = 1; int last = 0;
	for (int i = 1; i <= n * k; ++i) {

		int cur; fin >> cur;

		for (int j = 1; j < cur; ++j) {

			if (j == last || remain[j] == 0)
				continue;

			remain[j]--;

			memset(fr, 0, sizeof fr);
			for (int index = 1; index <= n; ++index)
				fr[remain[index]]++;

			ans += countNKperm(getHash(fr, remain[j]));

			remain[j]++;

		}

		remain[cur]--;
		last = cur;

	}

	fout << ans << '\n';

}

void solveB(void) {

	static int remain[dimn], fr[dimk];
	ll nkIndex; fin >> nkIndex;

	for (int i = 1; i <= n; ++i)
		remain[i] = k;

	int last = 0;
	for (int i = 1; i <= n * k; ++i) {
		for (int j = 1; j <= n; ++j) {
		
			if (j == last || remain[j] == 0)
				continue;

			--remain[j];

			memset(fr, 0, sizeof fr);
			for (int index = 1; index <= n; ++index)
				fr[remain[index]]++;

			ll nKcnt = countNKperm(getHash(fr, remain[j]));

			if (nKcnt >= nkIndex) {
				fout << j << ' ';
				last = j;
				break;
			}

			nkIndex -= nKcnt;
			++remain[j];

		}
	}

	fout << '\n';

}

int main() {

	int t;
	fin >> n >> k >> t;

	while (t--) {

		char op; fin >> op;

		if (op == 'A')
			solveA();
		else
			solveB();

	}

	return 0;

}

//Trust me, I'm the Doctor!