Cod sursa(job #135488)

Utilizator mariusdrgdragus marius mariusdrg Data 13 februarie 2008 20:51:14
Problema NKPerm Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.74 kb
#include<stdio.h>
#include<map>

using namespace std;

#define mkp make_pair
#define LL long long

const int maxn = 2010;


int a[maxn];
int i;
int n;
int k;
int x,p;
int nrp;
int j;
int b[maxn];
int t;
int ap;
int apa[maxn];
int ver[maxn];
map < pair<LL,int >, LL> m;
LL putere;

LL pow(int i,int put)
{
        LL ans = 1;
        for(;put;--put)
        {
                ans *= i;
        }
        return ans;
}

LL numara(LL ap,int ul)
{
      if (m[mkp(ap,ul)] != 0) return m[mkp(ap,ul)];
      if (ap == n * putere) return 1;

      LL pcur = 1;
      LL rez = 0;
      int i;
      for(i = 0;i <= k - 1; ++i)
      {
            int nrcur = (ap / pcur) % (n + 1);
            if (nrcur)
            {
                  if (i == ul)  rez += (LL)(nrcur - 1) * numara(ap - pcur + (pcur * (n + 1)),i + 1);
                        else rez += (LL)nrcur  * numara(ap - pcur + (pcur * (n + 1)),i + 1);
            }
            if (rez > ((LL)1 << 55))
            {
                  rez = (LL)1 << 55;
                  break;
            }
            pcur *= (n + 1);
      }
      m[mkp(ap,ul)] = rez;
      return rez;
}

int main()
{
        freopen("nkperm.in","r",stdin);
        freopen("nkperm.out","w",stdout);
        scanf("%d %d %d\n",&n,&k,&t);

        putere = 1;
        for(i = 1;i <= k; ++i)
        {
                putere *= (n + 1);
        }

        for(i = 1;i <= n; ++i)
        {
                ver[i] = k;
        }


        for(;t; --t)
        {
                char c;
                scanf("%c",&c);
                int i,j;
                if (c == 'A')
                {
                        for(i = 1;i <= n * k; ++i)
                        {
                              scanf("%d",&a[i]);
                              apa[i] = 0;
                        }
                        LL rez = 0;
                        ap = n;
                        for(i = 1;i <= n * k; ++i)
                        {
                              for(j = 1;j < a[i]; ++j)
                              {
                                    if (apa[j] < k && j != a[i - 1]) rez += numara(ap - pow(n + 1,apa[j]) + pow(n + 1,apa[j] + 1),apa[j] + 1);
                              }
                              ap -= pow(n + 1,apa[a[i]]);
                              apa[a[i]]++;
                              ap += pow(n + 1,apa[a[i]]);
                        }
                        printf("%lld\n",rez + 1);
                }
                if (c == 'B')
                {
                        scanf("%d",&x);
                        LL rez = 0;
                        int la = 0;
                        ap = 0;
                        for(i = 1;i <= n; ++i)
                        {
                              ap += 1;
                              apa[i] = 0;
                        }
                        for(i = 1;i <= n * k; ++i)
                        {
                                rez = 0;
                                for(j = 1;j <= n; ++j)
                                {
                                        if (apa[j] == k || j == la) continue;
                                        LL aux = numara(ap - pow(n + 1,apa[j]) + pow(n + 1,apa[j] + 1),apa[j] + 1);
                                        if (rez + aux >= x) break;
                                           else rez += aux;
                                }
                                printf("%d ",j);
                                la = j;
                                ap -= pow(n + 1,apa[j]);
                                apa[j]++;
                                ap += pow(n + 1,apa[j]);
                                x -= rez;

                        }
                        printf("\n");

                }
                scanf("\n");
        }
        return 0;

}