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

康托展开

时间:2019-08-17 00:39:22      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:进入   data   text   input   include   card   alt   container   eve   

直接进入正题。

康托展开

Description

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

Input

第一行有一个整数n(0<n<=100000);

随后有n行,每行是一个排列;

Output

输出一个整数m,占一行,m表示排列是第几位;

Sample Input
3
ABCDEFGHIJ
HGEBFACDJI
GDEDHJBXIA
Sample Output
1
2803322
1911924
 
其实思路可能不用说也能想出来
设总长度为len,枚举每一个字母,找它后面比它小的字母个数,记为k。那么每一位的答案就是k*(len-i)!。
下面给出草率证明:
先举个栗子,比如说一个字符串BACED。(样例太长懒得解释)
第一位B找到了A一个比它小的字母,说明这个字符串排在所有以A开头的字符串之后(显然共有4!个),所以B对最终答案的贡献是4!。
第二位A没找到比它小的字母,说明这个字符是所有以B开头的字符串中第二位最小的,所以B对最终答案没有贡献。
第三位C没找到比它小的字母,说明这个字符是所有以BA开头的字符串中第二位最小的,所以C对最终答案没有贡献。
第四位E找到了E一个比它小的字母,说明这个字符串排在所有以BACD开头的字符串之后(显然共有1!个),所以E对最终答案的贡献是1!。
第五位D没找到比它小的字母,说明这个字符是所有以BACE开头的字符串中第二位最小的,所以D对最终答案没有贡献。
又因为第一个字符串排名为1,所以所有字符串排名都应加1。
所以答案是1+4!+1!=26;
 
放代码,算是很短的。
技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n,f[19];
 5 int main(){
 6     scanf("%d",&n);
 7     f[0]=1;//注意 
 8     for(int i=1;i<=10;i++) f[i]=f[i-1]*i;//预处理阶乘 
 9     while(n--)//数据组数 
10     {
11         int ans=1;//每个字符串排名都加1,上面有提到 
12         string s;
13         cin>>s;
14         int len=s.length();//取字符串长度 
15         for(int i=0;i<len;i++)
16         {
17             int k=0;
18             for(int j=i+1;j<len;j++)
19                 if(s[i]>s[j]) k++;//记录在当前字符之后有几个比当前字符小的 
20             ans+=k*f[len-i-1];//注意i从0开始,所以是len-i-1 
21         }
22         printf("%d\n",ans);
23     }
24     return 0;
25 }
View Code

 

康托展开

标签:进入   data   text   input   include   card   alt   container   eve   

原文地址:https://www.cnblogs.com/Darkring/p/11366953.html

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