Cod sursa(job #120807)

Utilizator victorsbVictor Rusu victorsb Data 6 ianuarie 2008 18:02:44
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.6 kb
#include <cstdio>
#include <cstring>
#include <map>

using namespace std;

#define Nmax 21
#define Kmax 8
#define ll long long

int n, k, t;
ll INF;
int p[Nmax * Kmax];
int cnt[Nmax];
int ap[Kmax];
int pow[8];
map<int, ll> M;

void citire()
{
	scanf("%d %d %d\n", &n, &k, &t);
}

ll numara(int cnt[], int nr, int ultim)
{
    if (M.find(nr) != M.end())
		return M[nr];

	if (cnt[k] == n) return 1;

	int i;
	ll ret = 0;

    nr -= ultim * pow[k + 1];

	for (i = 0; i < k; ++i)
		if (cnt[i] > 0)
		{
			--cnt[i];
			nr -= pow[i];
			++cnt[i + 1];
			nr += pow[i + 1];
            nr += (i + 1) * pow[k + 1];


			if (i == ultim)
				ret += cnt[i] * numara(cnt, nr, i + 1);
			else
				ret += (cnt[i] + 1) * numara(cnt, nr, i + 1);

			if (ret >= INF)
			{
				ret = M[nr] = INF;
				return ret;
			}

			++cnt[i];
			nr += pow[i];
			--cnt[i + 1];
			nr -= pow[i + 1];
			nr -= (i + 1) * pow[k + 1];
		}

	nr += ultim * pow[k + 1];

	M[nr] = ret;
	return ret;
}

void solve()
{
	int i, j, q, ct = n * k, l, tmp;
	ll nr, doi55 = 1;
	char tip;

    INF = 1;
	INF <<= 56;
	doi55 <<= 55;

    pow[0] = 1;
	for (i = 1; i <= k + 1; ++i)
		pow[i] = pow[i - 1] * (n + 1);

	for (q = 1; q <= t; ++q)
	{
		scanf(" %c", &tip);
		if (tip == 'A')
		{
			for (i = 1; i <= ct; ++i)
				scanf(" %d", &p[i]);

			memset(cnt, 0, sizeof(cnt));

			nr = 0;
			for (i = 1; i <= ct; ++i)
			{
				for (j = 1; j < p[i]; ++j)
					if (cnt[j] < k && j != p[i - 1])
					{
						++cnt[j];

						memset(ap, 0, sizeof(ap));
						for (l = 1; l <= n; ++l)
							++ap[cnt[l]];
						
						for (tmp = l = 0; l <= k; ++l)
							tmp += ap[l] * pow[l];

						tmp += cnt[j] * pow[k + 1];

                        nr += numara(ap, tmp, cnt[j]);
						if (nr > INF) nr = INF;

						--cnt[j];
					}

				++cnt[p[i]];
			}

			if (nr <= doi55)
				printf("%lld\n", nr + 1);
			else
				printf("%lld\n", doi55);
		}
		else
		{
			scanf(" %lld", &nr);

            memset(cnt, 0, sizeof(cnt));
			for (i = 1; i <= ct; ++i)
			{
				for (j = 1; j <= n; ++j)
				{
					if (cnt[j] < k && j != p[i - 1])
					{
						p[i] = j;
						++cnt[j];

						memset(ap, 0, sizeof(ap));
						for (l = 1; l <= n; ++l)
							++ap[cnt[l]];

						tmp = 0;
						for (l = 0; l <= k; ++l)
							tmp += ap[l] * pow[l];
						tmp += cnt[j] * pow[k + 1];

						if (numara(ap, tmp, cnt[j]) < nr)
						{
							nr -= numara(ap, tmp, cnt[j]);
							--cnt[j];
						}
						else
							break;
					}
				}
			}

			for (i = 1; i <= ct; ++i)
				printf("%d ", p[i]);
			printf("\n");
		}
	}
}

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

	citire();
	solve();

	return 0;
}