Cod sursa(job #365141)

Utilizator tvladTataranu Vlad tvlad Data 17 noiembrie 2009 22:37:21
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2 kb
#include <cstdio>
#include <map>
using namespace std;

const int N = 20;
const int BASE = N+1;
const int K = 8;
const long long REZ = ((long long)1) << 55;

int n,k,t;
map<int, long long> m;

int code ( int f[], int last ) {
	int pw = 1, rez = 0;
	for (int i = 0; i <= k; ++i, pw *= BASE) rez += pw*f[i];
	rez += pw*last;
	return rez;
}

void decode ( int code, int f[], int &last ) {
	int pw = 1;
	for (int i = 0; i <= k; ++i, pw *= BASE) f[i] = (code/pw) % BASE;
	last = (code/pw) % BASE;
}

long long count ( int conf ) {
	if (m.find(conf) != m.end())
		return m[conf];
	int f[K], last;
	decode(conf,f,last);
	if (f[0] == n) return 1;
	long long rez = 0;
	for (int i = 1; i <= k; ++i) {
		if (f[i] != 0) {
			--f[i]; ++f[i-1];
			rez += (f[i] + (i != last)) * count(code(f,i-1));
			if (rez > REZ) {
				rez = REZ;
				break;
			}
			++f[i]; --f[i-1];
		}
	}
	m[conf] = rez;
	return rez;
}

void a() {
	int ap[N];
	long long rez = 1;
	int last = -1, x;
	for (int i = 0; i < n; ++i) ap[i] = k;
	for (int i = 0; i < n*k; ++i) {
		scanf("%d",&x);
		--x;
		for (int j = 0; j < x; ++j) {
			if (ap[j] > 0 && j != last) {
				--ap[j];
				int f[K];
				memset(f,0,sizeof(f));
				for (int t = 0; t < n; ++t) ++f[ap[t]];
				rez += count(code(f,ap[j]));
				++ap[j];
			}
		}
		--ap[x];
		last = x;
	}
	printf("%lld\n",rez);
}

void b() {
	int ap[N];
	int last = -1;
	long long x;
	scanf("%lld",&x);
	for (int i = 0; i < n; ++i) ap[i] = k;
	for (int i = 0; i < n*k; ++i) {
		int j;
		long long s = 0;
		for (j = 0; j < n; ++j) {
			if (ap[j] > 0 && j != last) {
				--ap[j];
				int f[K];
				memset(f,0,sizeof(f));
				for (int t = 0; t < n; ++t) ++f[ap[t]];
				long long y = count(code(f,ap[j]));
				++ap[j];
				if (s + y >= x) break;
				s += y;
			}
		}
		x -= s;
		--ap[j];
		printf("%d ",j+1);
		last = j;
	}
	printf("\n");
}

int main() {
	freopen("nkperm.in","rt",stdin);
	freopen("nkperm.out","wt",stdout);
	scanf("%d %d %d",&n,&k,&t);
	for (int i = 0; i < t; ++i) {
		char cmd;
		scanf(" %c ",&cmd);
		if (cmd == 'A')
			a(); else
			b();
	}
}