题面
题意
给出一个字符串,和整数n,输出这个字符串的第n个全排列.
方法
考虑到由小写字母组成,共26个,可求出每一种字符的个数
一个字符一个字符来求,枚举当前位,用组合数求出此时后面排列的种类数,若比n大,再找下一位,反之,枚举下一位,若枚举完了仍没有符合条件的,则不可能
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T,TT,n,len,num[30],jc[25];
char ch[30],ans[30];
bool P;
ll zh(ll u,ll v)
{
return jc[u]/(jc[v]*jc[u-v]);
}
inline ll ys(ll gs)
{
ll i,j,res=1;
for(i=1;i<=26;i++)
{
if(!num[i]) continue;
res*=zh(gs,num[i]);
gs-=num[i];
}
return res;
}
inline void find(ll now)
{
if(now>len) return;
ll i,j,k;
for(i=1;i<=26;i++)
{
if(!num[i]) continue;
num[i]--;
k=ys(len-now);
if(n<=k)
{
ans[now]=(char)(i+96);
find(now+1);
P=1;
break;
}
else
{
n-=k;
num[i]++;
}
}
}
int main()
{
ll i,j;
jc[0]=jc[1]=1;
for(i=2;i<=20;i++)
{
jc[i]=jc[i-1]*i;
}
cin>>T;
TT=T;
while(T--)
{
P=0;
memset(num,0,sizeof(num));
scanf("%s%lld",ch+1,&n);
len=strlen(ch+1);
for(i=1;i<=len;i++)
{
num[ch[i]-96]++;
}
find(1);
// return 0;
printf("Case %lld: ",TT-T);
if(!P) printf("Impossible");
else
{
for(i=1;i<=len;i++)
{
printf("%c",ans[i]);
}
}
printf("\n");
}
}