题目
给一串长度不超过20的字符串,求n-th permutation of the string. 0<n<231
思路
先排序,求出当前串有K种组合,如果n大于k,显然impossible;
然后就是每个位置枚举字符,判断下合理性就行了;
char s[30];
long long f[22];
typedef struct item {
char c;
int num;
item() {c = '\0';num = 0;}
}item;
item p[20];
int tot;
void init() {
f[0] = 1;
for (int i = 1;i < 21;++i)
f[i] = 1ll*f[i-1]*i;
// Rep(i, 1, 20) cout << f[i] << endl;
}
long long calc() {
LL t1 = 0, t2 = 1;
for (int i = 0;i <= tot;++i) {
t1 += p[i].num;
t2 *= f[p[i].num];
}
// cout << f[t1] << ' ' << t2 << endl;
return f[t1] / t2;
}
void solve(int k, int len) {
if (calc() < k) {
printf("Impossible\n");
return ;
}
for (int i = 1;i <= len;++i) {
long long t = 0;
int j;
for (j = 0;j <= tot;++j) {
p[j].num--;
long long now = calc();
t += now;
if (t >= k) {
putchar(p[j].c);
k -= (t - now);
break;
}
p[j].num++;
}
if (p[j].num == 0) {
for (int o = j;o < tot;++o)
p[o] = p[o+1];
--tot;
}
}
puts("");
}
int main(int argc, const char * argv[])
{ int kase;cin >> kase;
init();
while(kase--) {
int k;
scanf("%s%d", s + 1,&k);
int len = strlen(s + 1);
sort(s + 1, s + 1 + len);
tot = 0;
p[tot].c = s[1];
p[tot].num = 1;
for (int i = 2;i <= len;++i) {
if (s[i] == s[i - 1]) p[tot].num++;
else {
++tot;
p[tot].c = s[i];
p[tot].num = 1;
}
}
printf("Case %d: ", ++nCase);
solve(k, len);
}
// showtime;
return 0;
}