Cod sursa(job #119860)

Utilizator sima_cotizoSima Cotizo sima_cotizo Data 3 ianuarie 2008 15:37:27
Problema NKPerm Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.49 kb
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;

long n,k,t;
long in[128];
long cate[16];
long ap[32];

struct lma{		// sursa a fost scrisa de 1 ian :) La multi ani, 2008!
	long A[16], B;
};

struct comp {
	bool operator()(lma fir, lma sec) {
		if ( fir.B<sec.B )
			return true;
		return (memcmp(fir.A, sec.A, sizeof(long)*(k+1))<0);
	}
};

map <lma, long long, comp> M;


/* returneaza cate permutari au un inceput dat
 * Mircea a observat ceva inteligent, si anume
 * ca intr-un prefix, conteaza mai putin ce
 * numere sunt pe o anumita poz, mai important
 * e cate numere se repeta de x ori = cate[x]
 */
long long numara(long ultim) {
	if ( cate[k]==n ) 
		return 1;
	lma tmp;
	memcpy(tmp.A, cate, sizeof(long)*(k+1));
	tmp.B = ultim;
	map<lma, long long>::iterator it = M.find(tmp);
	if ( it!=M.end() ) {	// exista memoizat
		return it->second;
	}

	long long ret=0;
	for (long i=0; i<k; ++i)
		if ( cate[i] ) {
			cate[i] --; cate[i+1] ++; // teoretic mai bagi una care aparea de i ori pana acu
			if ( i==ultim )
				ret += cate[i]*numara(i+1);
			else
				ret += (cate[i]+1)*numara(i+1);
			if ( ret>1ll<<55 )
				return 1ll<<55;
			cate[i+1] --; cate[i]++;
		}

	M.insert(make_pair(tmp, ret));
	return ret;
}

long long a() {
	memset(cate,0,sizeof(cate));
	memset(ap,0,sizeof(ap));
	long long ret = 1;	// TODO de ce?
    cate[0] = n;
	for (long i=0; i<n*k; ++i) {
		for (long j=1; j<in[i]; ++j) 
			if ( j!=in[i-1] && ap[j] < k ) {
				cate[ap[j]] --;
				cate[++ap[j]]++;
				ret+= numara(ap[j]);
                cate[ap[j]] --;
                cate[--ap[j]] ++;
			}
        cate[ap[in[i]]]--;
		cate[++ap[in[i]]]++;
	}
	return ret;
}

void b(long long nr) {
	memset(ap,0,sizeof(ap));
	memset(cate,0,sizeof(cate));
    cate[0] = n;
	for (long i=0; i<n*k; ++i) {
		for (long j=1; j<n; ++j)
			if ( j!=in[i-1] && ap[j]<k ) {
				cate[ap[j]]--; cate[++ap[j]]++;
				long tmp;
				if ( (tmp=numara(ap[j]))>=nr ) {
					in[i] = j; 
					break;
				} else {
					nr -= tmp;
				}
				cate[ap[j]]--; cate[--ap[j]]++;
			}
		ap[in[i]]++;
	}
}

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

	scanf("%ld %ld %ld\n", &n, &k, &t);
	while ( t-- ) {
		char c;
		scanf("%c", &c);
		if ( c=='A' ) {
			for (long i=0; i<n*k; ++i)
				scanf("%ld", in+i);
			scanf("\n");
			printf("%lld\n", a());
		} else {
			long long nr;
			scanf("%lld\n", &nr);
			b(nr);
			for (long i=0; i<n*k; ++i)
				printf("%ld ", in[i]);
			printf("\n");
		}
	}

	fclose(stdin);fclose(stdout);
	return 0;
}