码迷,mamicode.com
首页 > 其他好文 > 详细

我排第几个---康托展开

时间:2015-05-05 14:25:42      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:nyoj   我排第几个   康托展开   

我排第几个

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
描述

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

输入
第一行有一个整数n(0<n<=10000);
随后有n行,每行是一个排列;
输出
输出一个整数m,占一行,m表示排列是第几位;
样例输入
3
abcdefghijkl
hgebkflacdji
gfkedhjblcia
样例输出
1
302715242
260726926
利用康托展开可以轻松解决这题,
在百度百科上看到一个类似的题
1324是{1,2,3,4}排列数中第几个大的数:
第一位是1小于1的数没有,是0个 0*3! 第二位是3小于3的数有1和2,
但1已经在第一位了,所以只有一个数2 1*2! 。
第三位是2小于2的数是1,但1在第一位,所以有0个数 0*1! ,
所以比1324小的排列有0*3!+1*2!+0*1!=2个,1324是第三个小数。
ps:康托展开公式X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 
#include <stdio.h>
#include <string.h>

bool visited[20];
int f(int x){
	if (x == 1 || x == 0)
		return 1;
	return x * f(x - 1);
}
int main(){
	int n;
	char a[13];
	scanf("%d", &n);
	getchar();
	int i, j;
	while (n--){
		int sum = 0;
		memset(visited, 0, sizeof(visited));
		gets(a);
		for (i = 0; i < 12; i++){
			visited[a[i] - 97] = 1;
			int res = 0;
			for (j = 0; j < a[i] - 97; j++)
			if (!visited[j])
				res++;
			sum += res * f(11 - i);
		}
		printf("%d\n", sum + 1);
	}
	return 0;
}


我排第几个---康托展开

标签:nyoj   我排第几个   康托展开   

原文地址:http://blog.csdn.net/u013174702/article/details/45501567

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!