X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a*0!其中,a[i]为整数,并且X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a*0!。这就是康托展开。
详解:http://blog.csdn.net/lttree/article/details/24798653
#include <stdio.h>
#include <string.h>
int main()
{
char a[13];
while(~scanf("%s",a))
{
long int f[]={1,1,2,6,24,120,720,5040,40320,362880};
long long ans=0;
int len=strlen(a);
for(int i=0;i<len;i++)
{
int tnt=0;
for(int j=i+1;j<len;j++)
if(a[i]>a[j]) ++tnt;
ans+=tnt*f[len-i-1];
}
printf("%lld\n",ans+1);
}
return 0;
}
//如4213排第20(从0开始
#include<bits/stdc++.h>
using namespace std;
int fac[] = {1,1,2,6,24,120,720,5040,40320};
char s[10];
//康托展开的逆运算,{1...n}的全排列,中的第k个数为s[]
void nikangtuo(int n,int k,char s[])
{
int i, j, flag, vst[16]={0};
--k;//由于从0开始
for (i=0; i<n; i++)
{
flag = k/fac[n-i-1];
for (j=1; j<=n; j++)
if (!vst[j])
{
if (flag == 0)
{
vst[j]=1;
printf("%d",j);
break;
}
--flag;
}
k %= fac[n-i-1];
}
}
int main()
{
int n,k;
while(cin>>n>>k)
{
kangtuo(n,k,s);
for(int i=0;i<n;i++)
printf("%c ",s[i]);
puts("");
}
return 0;
}
//知第20求出此排列