题意:觉得这里讲的不错 点击打开链接 ,详细看代码
#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; }