Cod sursa(job #380082)

Utilizator raduzerRadu Zernoveanu raduzer Data 4 ianuarie 2010 19:07:01
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.7 kb
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
using namespace std;

#define mp make_pair
#define pb push_back
#define x first
#define y second
#define pii pair<int, int>
#define pdd pair<double, double>
#define pid pair<int, double>
#define pdi pair<double, int>
#define ppi pair<pair<int, int>, int>
#define forit(it, v) for(__typeof(v.begin()) it = v.begin(); it != v.end(); ++it)
#define sz(v) v.size()
#define del(it, v) v.erase(it)
#define db double
#define ll long long

const int INF = 0x3f3f3f3f;
const int MAX_N = 20;
const int MAX_M = 0;
const int MAX_L = 10;
const int B = 21;
const ll PT = ((ll)1) << 55;

int n, k, t;
map <int, ll> hash;
int f[MAX_N];

int make(int f[], int p) 
{
	int pow = 1, ret = 0;

	for (int i = 0; i <= k; ++i, pow *= B) 
		ret += pow * f[i];

	return ret + pow * p;
}

inline ll numara(int cf) 
{
	if (hash.find(cf) != hash.end())
		return hash[cf];

	int h[MAX_L], p;

	int pow = 1;

	for (int i = 0; i <= k; ++i, pow *= B)
		h[i] = (cf / pow) % B;
	p = (cf / pow) % B;

	if (h[0] == n) 
		return 1;

	ll ret = 0;

	for (int i = 1; i <= k; ++i) 
		if (h[i]) 
		{
			--h[i]; 
			++h[i - 1];

			ret += (h[i] + (i != p)) * numara(make(h, i - 1));

			if (ret > PT) 
			{
				ret = PT;
				break;
			}

			++h[i]; 
			--h[i-1];
		}

	return hash[cf] = ret;
}

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

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

	for (; t; --t) 
	{
		char c;
		int d[MAX_L];

		scanf(" %c", &c);

		if (c == 'A')
		{
			ll sol = 1;
			int p = -1, nr;

			for (i = 0; i < n; ++i) 
				f[i] = k;

			for (i = 0; i < n * k; ++i) 
			{
				scanf("%d", &nr);
				--nr;

				for (j = 0; j < nr; ++j) 
					if (f[j] > 0 && j != p) 
					{
						--f[j];

						memset(d, 0, sizeof(d));

						for (l = 0; l < n; ++l) 
							++d[f[l]];

						int q = make(d, f[j]);

						sol += numara(q);
						++f[j];
					}

				--f[nr];
				p = nr;
			}
			printf("%lld\n", sol);

		}
		else
		{
			int p = -1;
			ll nr;

			scanf("%lld", &nr);

			for (i = 0; i < n; ++i) 
				f[i] = k;

			for (i = 0; i < n * k; ++i) 
			{
				ll sol = 0;

				for (j = 0; j < n; ++j) 
					if (f[j] > 0 && j != p) 
					{
						--f[j];

						memset(d, 0, sizeof(d));

						for (l = 0; l < n; ++l)
							++d[f[l]];

						int q = make(d, f[j]);

						ll z = numara(q);

						++f[j];

						if (sol + z >= nr) break;
						sol += z;
					}

				nr -= sol;
				--f[j];
				p = j;

				printf("%d ", j + 1);
			}

			printf("\n");
		}
	}
}