Cod sursa(job #118916)

Utilizator gcosminGheorghe Cosmin gcosmin Data 28 decembrie 2007 13:10:24
Problema NKPerm Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.61 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<int, LL> > hash[1 << 15];

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

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

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

	if (val != -1) hash[q].push_back(MP(w, 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) {
		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);
	}

	if (a / w == N) {
		find(MP(a, last), 1);
		return 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;

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

	for (i = 1; i <= q; i++) {
		nr[a[i]]++;

		if (i == q) last = nr[a[i]];
	}

	for (i = 1; i <= N; i++) rez[nr[i]]++;

	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;

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

			rez += calc(make_cod(jeg), last);

			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;
}