Cod sursa(job #116428)

Utilizator alextheroTandrau Alexandru alexthero Data 18 decembrie 2007 16:43:06
Problema NKPerm Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.07 kb
#include <stdio.h>
#include <string.h>
#include <vector>
#include <map>

#define nmax 50 
#define kmax 50 
#define pb push_back

using namespace std;
typedef long long LL;
typedef pair<vector<int>, int> vi;

map <vi, LL> M;
int n, k;
int crt[nmax * kmax], a[kmax];
vi init;
LL inf;

LL count(vi x)
{
	if(M.find(x) != M.end()) return M[x];
	if(x.first[k] == n) return 1;
	LL rez = 0;
	vi ns;
	for(int i = 0; i < k; i++)
		if(x.first[i])
		{
			ns = x;
			ns.first[i]--;
			ns.first[i + 1]++;
			ns.second = i + 1;
			if(i == x.second) rez += (x.first[i] - 1) * count(ns);
			else rez += x.first[i] * count(ns);
			if(rez > inf)
			{
				rez = inf;
				M[x] = rez;
				return rez;
			}
		}
	M[x] = rez;
	return rez;
}

LL oper1()
{
	LL rez = 1;
	memset(a, 0, sizeof(a));
	vi st = init, ns;
	for(int i = 1; i <= n * k; i++)
	{
		for(int j = 1; j < crt[i]; j++)
			if(j != crt[i - 1] && a[j] < k)
			{
				ns = st;
				ns.first[a[j]]--;
				ns.first[a[j] + 1]++;
				ns.second = a[j] + 1;
				rez += count(ns);
			}
		a[crt[i]]++;
		st.first[a[crt[i]] - 1]--;
		st.first[a[crt[i]]]++;
	}

	return rez;
}

void oper2(LL x)
{
	LL rez = 0;
	memset(a, 0, sizeof(a));
	vi st = init, ns;
	for(int i = 1; i <= n * k; i++)
	{
		for(int j = 1; j <= n; j++)
			if(j != crt[i - 1] && a[j] < k)
			{
				ns = st;
				ns.first[a[j]]--;
				ns.first[a[j] + 1]++;
				ns.second = a[j] + 1;
				if(rez + count(ns) >= x)
				{
					crt[i] = j;
					break;
				}
				else rez += count(ns);
			}
		a[crt[i]]++;
		st.first[a[crt[i]] - 1]--;
		st.first[a[crt[i]]]++;
	}

	for(int i = 1; i <= n * k; i++) printf("%d ", crt[i]); printf("\n");
}

int main()
{
	char ch;
	int t;
	LL a1;
	inf = (LL)1 << 56;

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

	scanf("%d %d %d\n", &n, &k, &t);

	init.first.pb(n);
	for(int i = 1; i <= k; i++) init.first.pb(0);
	init.second = 0;

	for(int i = 1; i <= t; i++)
	{
		scanf("%c ", &ch);
		if(ch == 'A')
		{
			for(int j = 1; j <= n * k; j++) scanf("%d", &crt[j]);
			scanf("\n");
			printf("%Ld\n", oper1());
		}
		else 
		{
			scanf("%Ld\n", &a1);
			oper2(a1);
		}
	}

	return 0;
}