Cod sursa(job #109671)

Utilizator gcosminGheorghe Cosmin gcosmin Data 25 noiembrie 2007 12:19:43
Problema NKPerm Scor 30
Compilator cpp Status done
Runda preONI 2008, Runda 1, Clasele 11-12 Marime 3.33 kb
#include <stdio.h>
#include <vector>
#include <map>
using namespace std;

#define LL long long

int N, K, T;

LL *jeg[600000];

char modk[600000];
int divk[600000];

void aloca(int lim)
{
	int i;
	for (i = 0; i <= lim; i++) jeg[i] = (LL *) malloc((N + 1) * sizeof(LL));
}

int limn[] = {0, 19, 11, 8, 6, 5, 0};

int pok[30];

int a[120];

void calc_din()
{
	N++;

	int lim = 0, i, j, q;

	pok[0] = 1;
	for (i = 1; i < N; i++) pok[i] = pok[i-1] * (K + 1);

	for (i = 0; i < N; i++) lim += pok[i] * K;

	aloca(lim);

	for (i = 1; i <= lim; i++) {
		modk[i] = modk[i - 1] + 1;
		if (modk[i] == (K + 1)) modk[i] = 0;

		divk[i] = i / (K + 1);
	}

	LL s;
	int ii;
	for (i = 1; i <= lim; i++) {
		s = 0; ii = i;
		for (j = 0; j < N; j++, ii = divk[ii]) {
			if (modk[ii] == 0) continue;

			q = i;
			q -= pok[j];
			if (!q) jeg[i][j] = 1;
			else jeg[i][j] = jeg[q][N] - jeg[q][j];

			s += jeg[i][j];
		}

		jeg[i][N] = s;
	}
}

LL fact[30];

void calc_fact()
{
	fact[0] = 1;
	for (int i = 1; i <= 20; i++) fact[i] = fact[i-1] * i;
}

void rep_A1(int a[], int N, int K)
{
	int i, j;
	LL rez = 0;

	for (i = 1; i <= N; i++) {
		for (j = 1; j < a[i]; j++) rez += fact[N - i];

		for (j = i + 1; j <= N; j++) if (a[j] > a[i]) a[j]--;
	}

	printf("%lld\n", rez + 1);
}

void rep_b1(LL nr, int N, int K)
{
	LL nrc = 0, i, j;

	for (i = 1; i <= N; i++) {
		for (j = 1; j <= N - i + 1; j++) {
			if (nrc + fact[N - i] >= nr || nrc + fact[N - 1] < 0) break;

			nrc += fact[N - i];
		}

		a[i] = j;
	}

	for (i = N; i >= 1; i--)
		for (j = i + 1; j <= N; j++) if (a[j] >= a[i]) a[j]++;

	for (i = 1; i <= N; i++) printf("%d ", a[i]);
	printf("\n");
}

void rep_A(int a[], int N, int K)
{
	int i = 0, sr = 0, j;
	LL rez = 0;
	while (N - 1 > limn[K]) {
		N -= 2; i += K + K; sr += 2;
	}

	int q = 0;
	for (i = 0; i < N; i++) q += pok[i] * K;

	for (i = sr * K + 1; i <= (N + sr) * K; i++) {
		for (j = 1; j < a[i] - sr; j++) {
			if ((q / pok[j - 1]) % (K + 1) == 0) continue;
			if (j + sr == a[i-1]) continue;

			rez += jeg[q][j-1];
		}

		q -= pok[a[i] - sr - 1];
	}

	printf("%lld\n", rez + 1);
}

void rep_b(LL nr, int N, int K)
{
	int i = 0, j, sr = 0;

	while (N - 1 > limn[K]) {
		for (j = i + 1; j <= i + K + K; j += 2) a[j] = sr + 1, a[j + 1] = sr + 2;
		N -= 2; i += K + K; sr += 2;
	}

	int q = 0;
	for (i = 0; i < N; i++) q += pok[i] * K;

	LL nrc = 0;
	for (i = sr * K + 1; i <= (N + sr) * K; i++) {
		for (j = 1; j <= N; j++) {
			if ((q / pok[j-1]) % (K + 1) == 0) continue;
			if (j + sr == a[i-1]) continue;
			if (nrc + jeg[q][j-1] >= nr || nrc + jeg[q][j-1] < 0) break;

			nrc += jeg[q][j-1];
		}

		q -= pok[j - 1];
		a[i] = j + sr;
	}

	for (i = 1; i <= (N + sr) * K; i++) printf("%d ", a[i]);
	printf("\n");
}

int main()
{
	int i, j;
	char op;

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

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

	LL nr;

	if (K == 1) {
		calc_fact();

		for (i = 1; i <= T; i++) {
			scanf(" %c", &op);
	
			if (op == 'A') {
				for (j = 1; j <= N * K; j++) scanf("%d", &a[j]);
	
				rep_A1(a, N, K);
			} else {
				scanf("%lld", &nr);

				rep_b1(nr, N, K);
			}
		}	

		return 0;
	}

	int na = N;

	N = limn[K];

	calc_din();

	N = na;

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

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

			rep_A(a, N, K);
		} else {
			scanf("%lld", &nr);

			rep_b(nr, N, K);
		}
	}

return 0;
}