Cod sursa(job #773718)

Utilizator darrenRares Buhai darren Data 2 august 2012 14:07:50
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.18 kb
#include <cstring>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <map>

using namespace std;

const int MAXN = 8;

int N, K, T;
int X[102], fr[22];
int power[22], fullbase;
map<int, long long> P;
long long number;

inline int getdigit(int num, int what)
{
	return (num / power[what]) % (N + 1);
}
long long getP(int num)
{
	if (num / MAXN == N * power[K]) return 1;
	if (P.find(num) != P.end()) return P[num];
	
	int last = num % MAXN, bitn = num / MAXN;
	
	long long resultnow = 0;
	for (int i = 0; i <= K - 1; ++i) // iau una cu frecventa i
	{
		if (getdigit(bitn, i) - (i == last) > 0)
			resultnow += (getdigit(bitn, i) - (i == last)) * getP((bitn - power[i] + power[i + 1]) * MAXN + i + 1);
		if (resultnow >= (1LL << 55))
		{
			resultnow = 1LL << 55;
			break;
		}
	}
	
	P[num] = resultnow;
	return resultnow;
}

int main()
{
	ifstream fin("nkperm.in");
	ofstream fout("nkperm.out");
	
	fin >> N >> K >> T;
	
	power[0] = 1;
	for (int i = 1; i <= K + 1; ++i)
		power[i] = power[i - 1] * (N + 1);
	
	for (int test = 1; test <= T; ++test)
	{
		char opt;
		
		fin >> opt;
		if (opt == 'A')
		{
			for (int i = 1; i <= N * K; ++i)
				fin >> X[i];
			
			memset(fr, 0, sizeof(fr));
			
			long long result = 1;
			for (int i = 1; i <= N * K; ++i)
			{
				int basenow = 0;
				for (int j = 1; j <= N; ++j)
					basenow += power[fr[j]];
				
				for (int j = 1; j < X[i]; ++j)
					if (j != X[i - 1] && fr[j] < K)
						result += getP((basenow - power[fr[j]] + power[fr[j] + 1]) * MAXN + (fr[j] + 1));
				
				++fr[X[i]];
			}
			
			fout << result << '\n';
		}
		else
		{
			fin >> number;
			--number;
			
			memset(fr, 0, sizeof(fr));
			
			int basenow = power[0] * N, last = -1;
			for (int i = 1; i <= N * K; ++i)
			{
				int j;
				for (j = 1; j <= N; ++j)
					if (j != last && fr[j] < K)
					{
						if (getP((basenow - power[fr[j]] + power[fr[j] + 1]) * MAXN + (fr[j] + 1)) <= number)
							number -= getP((basenow - power[fr[j]] + power[fr[j] + 1]) * MAXN + (fr[j] + 1));
						else 
							break;
					}
				
				basenow -= power[fr[j]];
				basenow += power[fr[j] + 1];
				++fr[j];
				
				fout << j << ' ';
				last = j;
			}
			
			fout << '\n';
		}
	}
	
	fin.close();
	fout.close();
}