Cod sursa(job #383545)

Utilizator CezarMocanCezar Mocan CezarMocan Data 16 ianuarie 2010 20:15:19
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.67 kb
#include <cstdio>
#include <map>
#include <vector>
#include <cstring>
#define maxN 22
#define maxK 7
#define baza (n + 1)

using namespace std;

int n, k, t;
int i, j, nr_ant;
int cta[maxN];
int init[maxN], pref[maxN], sol;
map <int, long long > dnk;
char ch;
long long nr, sum;


inline int vec_to_int(int t[]) {
	int i, nr = 0;
	for (i = 0; i < k + 2; i++)
		nr = nr * baza + t[i];
	return nr;
}

void int_to_vec(int nr, int t[]) {
	int i = k + 1;

	while (nr) {
		t[i] = nr % baza;
		nr /= baza;
		i--;
	}

	for (; i >= 0; i--)	t[i] = 0;
}

long long count(int stare) {
	int i, aux;
	int z[maxK], st[maxK];
	long long sol = 0;
	int_to_vec(stare, st);

	if (dnk.find(stare) != dnk.end()) 
		return dnk[stare];
	
	if (st[k] == n) {
		dnk[stare] = 1;
		return 1;
	}

	for (i = 0; i < k; i++) 
		if (st[i] != 0) {
//			memcpy(z, st, sizeof(st));
			st[i]--; st[i + 1]++;
			aux = st[k + 1];
			st[k + 1] = i + 1;
	
			int vi = vec_to_int(st);

			if (i == aux)
				sol = sol + (st[i]) * count(vi);
			else
				sol = sol + (st[i] + 1) * count(vi);
			if (sol > (1LL << 55)) {
				sol = (1LL << 55);
				break;
			}

			st[i]++; st[i + 1]--;
			st[k + 1] = aux;
		}

	dnk[stare] = sol;

	return sol;
}

int main() {
	freopen("nkperm.in", "r", stdin);
	freopen("nkperm.out", "w", stdout);
	
	scanf("%d%d%d", &n, &k, &t);


	for (; t > 0; t--) {
		scanf(" %c ", &ch);
		if (ch == 'A') {
			memset(pref, 0, sizeof(pref));
			memset(cta, 0, sizeof(cta));

			sum = nr_ant = 0;

			pref[0] = n;
			for (i = 1; i <= n * k; i++) {
				scanf("%lld", &nr);
				for (j = 1; j < nr; j++) 
					if (j != nr_ant && cta[j] < k) {
						pref[cta[j] + 1]++;
						pref[k + 1] = cta[j] + 1;
						pref[cta[j]]--;

						sum = sum + count(vec_to_int(pref));

						pref[cta[j] + 1]--;
						pref[k + 1] = 0;
						pref[cta[j]]++;
					}

				cta[nr]++;
				pref[cta[nr]]++;
				pref[cta[nr] - 1]--;
				nr_ant = nr;
			}

			printf("%lld\n", sum + 1);
		}
		else {
			scanf("%lld", &nr);
			sum = 0;
			memset(pref, 0, sizeof(pref));
			pref[0] = n;
			memset(cta, 0, sizeof(cta));

			nr_ant = 0;

			for (i = 1; i <= n * k; i++) {
				sum = 0;
				for (j = 1; j <= n; j++) 
					if (j != nr_ant && cta[j] < k) {
						pref[cta[j] + 1]++;
						pref[k + 1] = cta[j] + 1;
						pref[cta[j]]--;

						if (sum + count(vec_to_int(pref)) >= nr) {
							nr -= sum;
							sol = j;
							pref[cta[j] + 1]--;
							pref[k + 1] = 0;
							pref[cta[j]]++;			
							break;
						}

						sum = sum + count(vec_to_int(pref));
					
						pref[cta[j] + 1]--;
						pref[k + 1] = 0;
						pref[cta[j]]++;
					}

				cta[sol]++;
				pref[cta[sol]]++;
				pref[cta[sol] - 1]--;
				nr_ant = sol;
				printf("%d ", sol);
			}

			printf("\n");
		}
	}

	return 0;
}