Cod sursa(job #718178)

Utilizator GrimpowRadu Andrei Grimpow Data 20 martie 2012 16:40:53
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.85 kb
#include <stdio.h>
#include <vector>
using namespace std;
#define INF ((long long) 1 << 56)
#define MP make_pair

int N, K;

int a[110];

vector <pair<int, long long> > hash[1 << 15];

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

	vector <pair<int, long long> > :: 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;
}

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

	long long 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 + 1;
			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];

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

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

	return rez;
}

inline vector <int> get_pref(int a[], int q, int &last)
{
	int i;

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

long long get_nr(int a[], int q)
{
	int i, j, w, last = 0, n0;
	long long rez = 0;
	vector <int> 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(long long nr)
{
	int i, j, last = 0;
	long long rez = 0, q;
	vector <int> 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;
	long long 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;
}