Cod sursa(job #184241)

Utilizator DorinOltean Dorin Dorin Data 23 aprilie 2008 12:35:09
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.46 kb
# include <map>
# include <fstream>

using namespace std;

# define lim 1LL<<55

map <int, long long> c;
# define m ((k)*(n))

char tip;
int n,k,T;

ifstream fin ( "nkperm.in" );
ofstream fout ( "nkperm.out" );

int getcode(int * a,int ret)
{
	 int val=n;
	 for(int i = 1; i <= k; i++)  ret+= a[i] * val,val*=n;
	 return ret;
}

long long numara(int * a, int last)
{
	 long long ret;
	 int x;
	 x = getcode(a,last);
     if(c[x])return c[x];
     if( a[k] == n ) return 1;
     ret = 0;
     for(int i = 0; i < k ; i++)
         if(a[i])
         {
                 a[i]--;
                 a[i+1]++;
                 if(i == last)
                     ret+= (long long)a[i] * numara(a,i+1);
                 else
                     ret+= (long long)(a[i] + 1) * numara(a,i+1);
                 a[i]++;
                 a[i+1]--;
                 if(ret >= lim) {
                        c[x] = lim;
                        return lim;
                 }
         }
     c[x] = ret;
     return ret;
}

void detA()
{
     long long ret = 0;
     int i;
	 int aparitii[21]={0};
	 int numar[6]={0},perm[101];
	 numar[0] = n;
     
	 perm[0] = 0;
	 for(i = 1; i<= m; i++)
		   fin >> perm[i];
	 for(i = 1; i <= m; i++)
	 {
		   for(int x = 1; x < perm[i]; x++)
		   {
               if(x != perm[i-1] && aparitii[x] < k)
               {
			       numar[aparitii[x]]--;
			       numar[aparitii[x]+1]++;

    			   ret += numara(numar,aparitii[x]+1);

	    		   numar[aparitii[x]]++;
		    	   numar[aparitii[x]+1]--;
               }
		   }
		   aparitii[perm[i]]++;
		   numar[aparitii[perm[i]]]++;
           numar[aparitii[perm[i]] - 1] --;
     }
     
	 fout << ret+1 << "\n";
}
void detB()
{
	long long r = 0,x;
	int ultim  = 0;
	fin >> x;

	int numar[6] = {0},aparitii[21] = {0};
	numar[0] = n;
	int i,j;

	for(i = 1; i <= m; i++)
	{
		for( j = 1; j<=n;j++)
			if(j != ultim && aparitii[j] < k)
			{
				numar[aparitii[j]] --;
				aparitii[j] ++;
				numar[aparitii[j]] ++;
				r = numara(numar,aparitii[j]);
				if(r >= x) break;
				x -= r;
				numar[aparitii[j]]--;
				aparitii[j]--;
				numar[aparitii[j]]++;
			}
		ultim = j;
		fout << j << " ";
	}

	fout << "\n";
}

int main()
{
	fin >> n >> k >> T;
    while(T--)
    {
       fin >> tip;
       switch(tip)
       {
           case 'A' : detA(); break;
           case 'B' : detB(); break;
       }
    }
    
    return 0;
}