Cod sursa(job #966301)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 25 iunie 2013 18:06:17
Problema NKPerm Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.58 kb
#include<stdio.h>
#include<vector>

#define maxn 21
#define maxk 7
#define mod 262143

using namespace std;

FILE*f=fopen("nkperm.in","r");
FILE*g=fopen("nkperm.out","w");

const long long stop = (1LL<<55);

int n,k,tests,elem,base;
int P[maxn*maxk],pbase[maxk],ap[maxn];
long long r;
vector< pair< long long , pair<int,int> > >H[mod+5];

inline int get_digit ( int x , const int &c ){
	
	for ( int i = 0 ; i < c ; ++i ){
		x /= base;
	}
	return x % base;
}

inline void set_digit ( int &x , const int &c , const int &value ){
	
	int before = get_digit(x,c);
	x -= pbase[c]*before;
	x += pbase[c]*value;
}

inline void insert ( const int &a , const int &b , const long long &r ){
	int h = (a*b)&mod;
	
	H[h].push_back(make_pair(r,make_pair(a,b)));
}

inline long long search ( const int &a , const int &b ){
	int h = (a*b)&mod;
	
	for ( vector< pair< long long , pair<int,int> > >::iterator itt = H[h].begin() ; itt != H[h].end() ; ++itt ){
		pair<int,int>x = itt->second;
		if ( x.first == a && x.second == b )	return itt->first;
	}
	
	return -1;
}

inline void initializari () {
	
	elem = n*k; base = n+1;
	pbase[0] = 1;
	for ( int i = 1 ; i <= k ; ++i ){
		pbase[i] = pbase[i-1]*base;
	}
	
	int basic_conf = 0;
	set_digit(basic_conf,k,n);
	insert(basic_conf,k,1);
}

inline long long dinamica ( int conf , int last ){
	long long r = search(conf,last);
	if ( r != -1 )	return r;
	
	long long s = 0;
	for ( int i = 0 ; i < k ; ++i ){
		int cate = get_digit(conf,i);
		if ( cate == (i==last) )	continue ;
		
		int new_conf = conf;
		set_digit(new_conf,i,cate-1);
		set_digit(new_conf,i+1,get_digit(conf,i+1)+1);
		
		s += dinamica(new_conf,i+1)*(cate - (i==last));
		if ( s > stop ){
			s = stop;
			break ;
		}
	}
	
	insert(conf,last,s);
	return s;
}

inline void solveA () {
	long long r = 0;
	
	for ( int i = 1 ; i <= n ; ++i ){
		ap[i] = 0;
	}
	
	for ( int i = 1 ; i <= elem ; ++i ){
		fscanf(f,"%d\n",&P[i]);
	}
	P[0] = -1;
	
	int conf = 0;
	set_digit(conf,0,n);
	
	for ( int i = 1 ; i <= elem ; ++i ){
		
		for ( int j = 1 ; j < P[i] ; ++j ){
			if ( ap[j] == k || j == P[i-1] )	continue ;
			
			int new_conf = conf;
			set_digit(new_conf,ap[j],get_digit(conf,ap[j])-1);
			set_digit(new_conf,ap[j]+1,get_digit(conf,ap[j]+1)+1);
			
			r += dinamica(new_conf,ap[j]+1);
		}
		
		set_digit(conf,ap[P[i]],get_digit(conf,ap[P[i]])-1);
		set_digit(conf,ap[P[i]]+1,get_digit(conf,ap[P[i]]+1)+1);
		++ap[P[i]];
	}
	
	++r;
	fprintf(g,"%lld\n",r);
}

inline void solveB () {
	
	long long ind;
	fscanf(f,"%lld\n",&ind);
	
	for ( int i = 1 ; i <= n ; ++i ){
		ap[i] = 0;
	}
	
	int conf = 0;
	set_digit(conf,0,n);
	
	int last = -1;
	for ( int i = 1 ; i <= elem ; ++i ){
		
		int pun = 0;
		for ( int j = 1 ; j <= n ; ++j ){
			if ( j == last || ap[j] == k )	continue ;
			
			int new_conf = conf;
			set_digit(new_conf,ap[j],get_digit(conf,ap[j])-1);
			set_digit(new_conf,ap[j]+1,get_digit(conf,ap[j]+1)+1);
			
			long long now = dinamica(new_conf,ap[j]+1);
			
			if ( now < ind ){
				ind -= now;
			}
			else{
				pun = j;
				break ;
			}
		}
		
		fprintf(g,"%d ",pun);
		set_digit(conf,ap[pun],get_digit(conf,ap[pun])-1);
		set_digit(conf,ap[pun]+1,get_digit(conf,ap[pun]+1)+1);
		++ap[pun];
		last = pun;
	}
	fprintf(g,"\n");
}

int main () {
	
	fscanf(f,"%d %d %d\n",&n,&k,&tests);
	
	initializari();
	
	while ( tests-- ){
		char tip;
		fscanf(f,"%c",&tip);
		
		if ( tip == 'A' ){
			solveA();
		}
		else{
			solveB();
		}
	}
	
	
	fclose(f);
	fclose(g);
	
	return 0;
}