描述
现在有"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; }