题意:觉得这里讲的不错 点击打开链接 ,详细看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 35;
char str[MAXN],result[MAXN],cword;
int vis[130],word[MAXN],cnt;
long long n,F[MAXN],len;
long long count(){
long long sum = 0,ans;
for (int i = 0; i < cnt; i++)
sum += vis[word[i]];
ans = F[sum];
for (int i = 0; i < cnt; i++)
if (vis[word[i]] > 1)
ans /= F[vis[word[i]]];
return ans;
}
int dfs(int cur,long long num){
if (cur == len)
return num;
long long sum = 0;
for (int i = 0; i < cnt; i++){
if (vis[word[i]]){ //尝试将最小的排在最外面
vis[word[i]]--;
long long s = count(); //剩下的会产生多少可能
if (sum <= num && sum+s >= num){ //结果一定要在这两个数之间
result[cur] = word[i];
return dfs(cur+1,num-sum);
}
else sum += s; //跳过当前的字典序,在加一个大的
vis[word[i]]++;
}
}
return -1;
}
int main(){
F[0] = F[1] = 1;
for (int i = 2; i < 16; i++)
F[i] = i * F[i-1];
int t,cas=1;
scanf("%d",&t);
while (t--){
scanf("%s%lld",str,&n);
int ok = 2;
len = strlen(str);
cnt = 0;
memset(vis,0,sizeof(vis));
for (int i = 0; i < len; i++){
if (!vis[str[i]])
word[cnt++] = str[i];
vis[str[i]]++; //记录单词出现的次数
}
cword = 0;
sort(word,word+cnt);
for (int i = 0; i < cnt; i++){
if (vis[word[i]] % 2){ //奇数次的只能有一个
ok--;
vis[word[i]]--;
cword = word[i];
}
}
if (cnt == 1 && n > 1)
ok = 0;
if (ok > 0){
len /= 2;
for (int i = 0; i < cnt; i++)
vis[word[i]] /= 2;
ok = dfs(0,n);
if (ok > 0){
int t = len;
if (cword)
result[t++] = cword;
for (int i = 0; i < len; i++)
result[t++] = result[len-i-1];
result[t] = '\0';
}
}
printf("Case %d: %s\n",cas++,ok>0?result:"XXX");
}
return 0;
}