Cod sursa(job #1971040)

Utilizator StarGold2Emanuel Nrx StarGold2 Data 19 aprilie 2017 19:39:20
Problema NKPerm Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.87 kb
#include <bits/stdc++.h>
using namespace std;

fstream in ( "nkperm.in" , ios::in  );
fstream out( "nkperm.out", ios::out );

const int KMAX = 5;
const int NMAX = 20;
const int NKMAX = 100;

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

unordered_map<int, long long> mmp;
int pwr[KMAX + 2], frq[NMAX + 1], arr[NKMAX + 1];

long long count( int msk, int n, int k ) {
    if( mmp.find( msk ) != mmp.end() )
        return mmp[msk];
    
    if( msk / pwr[k] % (n + 1) == n )
        mmp[msk] = 1;
    else {
        long long ans = 0;
        for( int i = 0; i < k; i ++ ) {
            if( msk / pwr[i] % (n + 1) == 0 )
                continue;
            
            msk -= pwr[i] - pwr[i + 1];
            
            ans += ( msk / pwr[i] % (n + 1) + ( i != msk / pwr[k + 1] ) ) *
                     count( msk % pwr[k + 1] + (i + 1) * pwr[k + 1], n, k );
            
            msk += pwr[i] - pwr[i + 1];
            
            if( ans >= INF )
                break;
        }
        
        mmp[msk] = min( INF, ans );
    }
    
    return mmp[msk];
}

int main( void ) {
    
    int n, k, t;
    in >> n >> k >> t;
    
    pwr[0] = 1;
    for( int i = 1; i <= k + 1; i ++ )
        pwr[i] = pwr[i - 1] * (n + 1);

    while( t -- ) {
        char ch;
        in >> ch;
        
        long long ans = 0;
        fill( frq + 1, frq + n + 1, 0 );
        
        if( ch == 'A' ) {
            for( int i = 1, msk = n; i <= n * k; i ++ ) {
                in >> arr[i];
                
                for( int j = 1; j < arr[i]; j ++ ) {
                    if( j == arr[i - 1] || frq[j] == k )
                        continue;
                    
                    msk -= pwr[frq[j]]; frq[j] ++; msk += pwr[frq[j]];
                    ans += count( msk + frq[j] * pwr[k + 1], n, k );
                    msk -= pwr[frq[j]]; frq[j] --; msk += pwr[frq[j]];
                }
                
                msk -= pwr[frq[arr[i]]]; frq[arr[i]] ++; msk += pwr[frq[arr[i]]];
            }
            
            out << ans + 1 << "\n";
        }
        else {
            long long val;
            in >> val;
            
            for( int i = 1, pos = 1, msk = n; i <= n * k; i ++, pos = 1 ) {
                for( int j = 1; j <= n; j ++, pos = j ) {
                    if( j == arr[i - 1] || frq[j] == k )
                        continue;
                    
                    msk -= pwr[frq[j]]; frq[j] ++; msk += pwr[frq[j]];
                    
                    if( ans +  count( msk + frq[j] * pwr[k + 1], n, k ) < val )
                        ans += count( msk + frq[j] * pwr[k + 1], n, k );
                    else
                        break;
    
                    msk -= pwr[frq[j]]; frq[j] --; msk += pwr[frq[j]];
                }
                
                arr[i] = pos; out << arr[i] << " ";
            }
            
            out << "\n";
        }
    }
    
    return 0;
}