(康托展开解释)+ NYOJ 139 我排第几个

描述

现在有"abcdefghijkl”12个字符,将其所有的排列中按字典序排列,给出任意一种排列,说出这个排列在所有的排列中是第几小的?

输入
第一行有一个整数n(0<n<=10000);
随后有n行,每行是一个排列;
输出
输出一个整数m,占一行,m表示排列是第几位;
样例输入
3
abcdefghijkl
hgebkflacdji
gfkedhjblcia
样例输出
1
302715242
260726926
来源
[苗栋栋]原创
上传者
苗栋栋
做这道题,请尊重你的第一想法,对,没错。就是按每一位来计算小于它的个数,然后相加。

比如·第一位是3 1 2 ,然后·就有比第一位3小的有2个 ,则有2*2!就是 123 132    213 231.......

按照这种思维有一个科学方法:康托展开 

先看一下它的公式:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 试试看,能看懂吗??

X为在这个排列之前的个数,最后别忘了加1哦

n为数组的长度;

a[n]是比第一位数小的个数,注意这里从0开始。(n-1)就不用解释了吧大笑

理解了就好做了,

最后可以先把1~12的竭诚用数组存起来,然后对于每一位i,有f[12-i]*t        t相当于a[i],比第i位小的个数;

参考链接:http://blog.csdn.net/zhongkeli/article/details/6966805

代码如下:

#include<stdio.h>
char s[15];
int n;
int main()
{
    int f[15];         //存阶乘;
    f[1] = 1;
    for(int i = 2; i <= 12; i++)
    {
        f[i] = f[i - 1] * i;  //计算相应的阶乘
    }
    scanf("%d",&n);
    while(n--)
    {
        int sum = 0;
        scanf("%s",s + 1);     //这里s+1比较好,第一位是是s[1];
        for(int i = 1; i <= 12; i++)
        {
            int t = 0;       //统计i后面的比,,,,,,自己看吧
            for(int j = i + 1; j <= 12; j++)
            {
                if(s[i] > s[j]) t++;
            }
            sum += f[12 - i] * t;         //相当于t=a[n]*(n-1)+.........    n-1==f[12-i]   t==a[n];    
        }
        printf("%d\n",sum+1);          //别忘了加1
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zitian246/article/details/77887108
今日推荐