新年第一题哈哈。虽然没有成功拿到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());
}
}
}