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