康拓展开逆康托展开

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求出此排列 



猜你喜欢

转载自blog.csdn.net/honeycomb_1/article/details/79505030