laekov

BZOJ3301 [USACO2011 Feb] Cow Line

新年第一题哈哈。虽然没有成功拿到fb。


所谓阶乘进制数么。略水。只不过加一减一啥的得小心些。


#include <cstdio>

#include <cstring>

#include <algorithm>


using namespace std;


typedef long long dint;


#define pow2(x) (1<<(x))

#ifdef WIN32

#define lld "%I64d"

#else

#define lld "%lld"

#endif


const int maxn = 21;


dint fac[maxn];

int n, k, t, x[maxn];

dint a;


void sovPerm() {

t = 0;

for (int i = n; i; -- i) {

int r = (a - 1) / fac[i - 1] + 1, c = 0;

a -= (r - 1) * fac[i - 1];

x[i] = 1;

while (1) {

if (!(t & pow2(x[i])))

++ c;

if (c == r)

break;

else

++ x[i];

}

t |= pow2(x[i]);

printf("%d%c", x[i], (i > 1 ? 32 : 10));

}

}


dint sovNum() {

dint s = 0;

t = pow2(n + 1) - 2;;

for (int i = 1; i <= n; ++ i) {

int c = 0;

for (int j = 1; j < x[i]; ++ j)

c += (t >> j) & 1;

s += fac[n - i] * c;

t &= ~pow2(x[i]);

}

return s + 1;

}


int main() {

#ifndef ONLINE_JUDGE

freopen("in.txt", "r", stdin);

#endif


scanf("%d%d", &n, &k);

fac[0] = 1;

for (int i = 1; i <= n; ++ i)

fac[i] = fac[i - 1] * i;

while (k --) {

char opt;

do

opt = getchar();

while (opt != 'P' && opt != 'Q');

if (opt == 'P') {

scanf(lld, &a);

sovPerm();

}

else {

for (int i = 1; i <= n; ++ i)

scanf("%d", x + i);

printf(lld "\n", sovNum());

}

}

}


评论

© laekov | Powered by LOFTER