Cod sursa(job #118908)

Utilizator gcosminGheorghe Cosmin gcosmin Data 28 decembrie 2007 12:57:55
Problema NKPerm Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.04 kb
#include <stdio.h>
#include <vector>
using namespace std;

#define LL long long
#define INF ((LL) 1 << 55)
#define MP make_pair
#define intl unsigned char

int N, K;

int a[110];

vector <pair<pair<int, int>, LL> > hash[1 << 19];

inline LL find(pair<int, int> a, LL val)
{
	int q = a.first * (N + 1) + a.second;
	q *= 524371;
	if (q < 0) q = -q;
	q >>= 13;

	vector <pair<pair<int, int>, LL> > :: iterator it;

	for (it = hash[q].begin(); it != hash[q].end(); ++it)
		if (it->first == a) return it->second;

	if (val != -1) hash[q].push_back(MP(a, val));

	return 0;
}

LL calc(int a, int last)
{
	LL jeg;
	if ((jeg = find(MP(a, last), -1))) return jeg;

	LL rez = 0;
	int q, w = 1;

	for (int i = 0; i < K; i++) w *= N + 1;

	if (a / w == N) {
		find(MP(a, last), 1);
		return 1;
	}

	w = 1;
	for (int i = 0; i < K; i++, w *= N + 1) {
		q = (a / w) % (N + 1);

		if (!q) continue;
		q--;

		a -= w;
		a += w * (N + 1);

		if (i == last) rez += q * calc(a, i + 1);
		else rez += (q + 1) * calc(a, i + 1);

		if (rez > INF) {
			rez = INF;
			break;
		}

		a += w;
		a -= w * (N + 1);
	}

	find(MP(a, last), rez);
	return rez;
}

int b[110];

int make_cod(vector <intl> jeg)
{
	int i = 0, rez = 0;

	for (i = K; i >= 0; i--) {
		rez = rez * (N + 1) + jeg[i];
	}

	return rez;
}

vector <intl> get_pref(int a[], int q, int &last)
{
	int i, j, nr, w = 0, kkt;

	vector <intl> rez(K + 1, 0);

	memcpy(b, a, sizeof(b));

	for (i = 1; i <= q; i++) {
		if (!b[i]) continue;

		kkt = b[i];
		nr = 0;
		for (j = i; j <= q; j++) 
			if (b[j] == kkt) {
				nr++, b[j] = 0;
				if (j == q) last = nr;
			}

		rez[nr]++;
		w++;
	}

	rez[0] = N - w;

	return rez;
}

LL get_nr(int a[], int q)
{
	int i, j, w, last, n0;
	LL rez = 0;
	vector <intl> jeg;

	vector <int> nr(N + 1, 0);

	for (i = 1; i <= q; i++) {
		w = a[i];
		for (j = 1; j < a[i]; j++) {
			if (j == a[i - 1] || nr[j] == K) continue;

//			printf("-- %d %d\n", i, j);

			a[i] = j;
			jeg = get_pref(a, i, last);
			n0 = jeg[0];

/*			for (int ii = 1; ii <= i; ii++) printf("%d ", a[ii]);
			printf("\n");
			for (int ii = 0; ii <= K; ii++) printf("%d ", jeg[ii]);
			printf("\n");
			printf("%d\n\n", last);
*/
			rez += calc(make_cod(jeg), last);

//			printf("%d %d - %lld\n", i, j, rez);

			a[i] = w;
		}

		nr[j]++;
	}

	return rez + 1;
}

void get_vec(LL nr)
{
	int i, j, last;
	LL rez = 0, q;
	vector <intl> jeg;
	vector <int> nnr(N+1, 0);

	for (i = 1; i <= N * K; i++) {
		for (j = 1; j <= N; j++) {
			if (j == a[i - 1] || nnr[j] == K) continue;
			a[i] = j;

			jeg = get_pref(a, i, last);
			q = calc(make_cod(jeg), last);
			if (rez + q < nr) rez += q;
			else break;
		}

		nnr[a[i]]++;
	}
}

int main()
{
	int T, I, i;
	char op;
	LL q;

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

	scanf("%d %d %d", &N, &K, &T);

	for (I = 1; I <= T; I++) {
		scanf(" %c", &op);

		if (op == 'A') {
			for (i = 1; i <= N * K; i++) scanf("%d", &a[i]);

			printf("%lld\n", get_nr(a, N * K));
		} else {
			scanf("%lld", &q);
			get_vec(q);
			for (i = 1; i <= N * K; i++) printf("%d ", a[i]);
			printf("\n");
		}
	}

return 0;
}