Cod sursa(job #379743)

Utilizator raduzerRadu Zernoveanu raduzer Data 3 ianuarie 2010 17:37:19
Problema NKPerm Scor 60
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.66 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 = 8;
const int B = 21;
const ll PT = ((ll)1) << 55;

int n, k, t;
int f[MAX_N], d[MAX_L];
map<int, ll> m;

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

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

	return ret + pow * p;
}

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

	int last;

	int pow = 1;

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

	last = (cf / pow) % B;

	if (d[0] == n) 
		return 1;
	
	ll rez = 0;

	for (int i = 1; i <= k; ++i) 
	{
		if (d[i] != 0) 
		{
			--d[i]; 
			++d[i - 1];
			rez += (d[i] + (i != last)) * numara(make(d, i-1));

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

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

	m[cf] = rez;
	return rez;
}

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 p = -1;
		ll nr;

		scanf(" %c ",&c);

		if (c == 'A')
		{
			ll rez = 1;

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

			for (i = 0; i < n * k; ++i) 
			{
				scanf("%lld", &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]];

						rez += numara(make(d, f[j]));
						++f[j];
					}
				}
				--f[nr];
				p = nr;
			}
		
			printf("%lld\n", rez);
		}
		else
		{
			scanf("%lld", &nr);

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

			for (i = 0; i < n * k; ++i) 
			{
				ll s = 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]];
		
						ll y = numara(make(d, f[j]));
						++f[j];

						if (s + y >= nr) break;

						s += y;
					}

				nr -= s;
				--f[j];
		
				printf("%d ", (p = j) + 1);
			}
		
			printf("\n");
		}
	}
}