Pagini recente » Cod sursa (job #2642573) | Viata de dupa olimpiade (partea II) | Istoria paginii runda/oni_11_12_6/clasament | Cod sursa (job #718179) | Cod sursa (job #2437420)
#include <fstream>
#include <cstring>
#include <map>
#define DIM 101
#define BASE 21
#define INF (1LL<<55)
using namespace std;
ifstream fin ("nkperm.in");
ofstream fout ("nkperm.out");
int v[DIM],f[DIM],frecv[7];
int t,n,k,i,j;
long long nr;
char c;
map <int,long long> d;
long long get_stare (int f[], int x){
/// vreau sa obtin codul din lista cu frecvente si ultimul element care trebuie pus
/// e ca si cum as scrie intr o alta baza numarul
long long sol = 0;
int p = 1;
for (int i=0;i<=k;i++){
sol += p*f[i];
p *= BASE;
}
sol += x*p; /// trebuie neaparat sa tin cont si de ultimul element
return sol;
}
void get_frecv (long long stare, int frecv[], int &last_frecv){
/// vreau sa obtin frecventele dintr o stare data
/// f[0] + f[1]*21 + f[2]*21^2 + f[3]*21^3 + f[4]*21^4 + f[5]*21^5 + last_frecv*21^6
int p = 1;
for (int i=0;i<=k;i++){
frecv[i] = (stare/p)%BASE;
p *= BASE;
}
last_frecv = (stare/p)%BASE;
}
long long get_nr (long long stare){
/// cate permutari de lungime lg care incep cu x am
/// cunoscand frecventele tuturor elmentelor
/// trebuie sa tin cont de ultimul element pus in permutare si de frecv lor
/// incerc sa autoapelez fixand urmatorul element
/// nu conteaza ce numere am pe frecvente
if (d.find(stare) != d.end()) /// inseamna ca am mai calculat deja pt stare
return d[stare];
memset (frecv,0,sizeof frecv);
int last_frecv = 0;
get_frecv (stare,frecv,last_frecv);
if (frecv[0] == n){
/// inseamna ca am ajuns la un sir de lungime 0
return 1;
}
long long sol = 0;
for (int i=1;i<=k;i++){
if (!frecv[i])
continue;
long long coef = frecv[i];
if (last_frecv == i) /// nu pot sa il plasez langa unul egal cu el
coef--;
/// incerc sa maresc frecventa unui element, deci frecventa curenta scade
frecv[i]--, frecv[i-1]++;
/// acum trebuie sa reconstruim codul
long long new_stare = get_stare (frecv,i-1);
sol += coef * get_nr (new_stare);
if (sol >= INF){ /// nu mai are sens sa continui
sol = INF;
break;
}
/// cand mai intorc trb sa revin la frecventele initiale
frecv[i]++, frecv[i-1]--;
}
d[stare] = sol;
return sol;
}
int main (){
fin>>n>>k>>t;
for (;t--;){
fin>>c;
for (i=1;i<=n;i++)
f[i] = k;
if (c == 'A'){
for (i=1;i<=n*k;i++){
fin>>v[i];
//poz[v[i]][i] = poz[v[i]][i-1]+1; /// cati de v[i] am pana la pozitia i
}
long long sol = 0;
for (i=1;i<=n*k;i++){
for (j=1;j<v[i-1];j++){
if (!f[j]) /// nu are sens sa mai incerc daca am frecv 0
continue;
if (j != v[i-1]){
/// trebuie sa obtin noile frecvente
f[j]--;
memset (frecv,0,sizeof frecv);
for (int val=1;val<=n;val++)
frecv[f[val]]++;
sol += get_nr(get_stare(frecv,f[j]));
f[j]++;
}}
f[v[i]]--;
}
fout<<sol<<"\n";
/// d[lg][i][j] - nr de permutari de lg lg, care se termina cu elementul i\
avand frecventa j se pot forma
/// cate permutari de lg lg se pot forma, cunoscand frecventele numerelor
/// nr de permurari in care elementul i apare de j ori
continue;
}
/// fac cam acelasi lucru
fin>>nr;
for (i=1;i<=n*k;i++){
for (j=1;j<=n;j++){ /// imi aleg ce element as vrea sa pun
if (!f[j])
continue;
if (j != v[i-1]){
f[j]--;
memset (frecv,0,sizeof frecv);
for (int val=1;val<=n;val++)
frecv[f[val]]++;
long long val = get_nr(get_stare(frecv,f[j]));
f[j]++;
if (val < nr)
nr -= val;
else {
/// inseamna ca trebuie sa ma opresc aici
v[i] = j;
f[j]--;
break;
}}}
fout<<v[i]<<" ";
}
fout<<"\n";
}
return 0;
}