首页 > 代码库 > NYOJ 139 我排第几个 康托展开式

NYOJ 139 我排第几个 康托展开式

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=139

 

思路:康托展开式的典型应用,康托展开式是什么呢,举个例子。1,2,3这三个数的全排列共有六种,那么按照字典的顺序,『3,2,1』 这个序列是在第几个呢。康托是这样想的:

    首先从第一位3开始看,比3小的有2,1,那么也就是说如果第一位是1或者2都在这个序列的前面,那么以1或者2开头的序列有多少呢,答案为2*2!。为什么是这个答案呢?因为符合 要求的第一位共有1和2两个数,然后第二位和第三位组成的排列总数为2!,所以,学过排列组合的都知道,乘起来就可以了(康托展开式本来就是组合数学里面的...)。

 

好了,既然我们明白了康托展开式是什么,下面就可以写代码了。

 

代码如下:

  

#include <iostream>#include <cstring>using namespace std;int jc[]={1,2,6,24,120,720,5040,40320,362880,3628800,39916800};//阶乘数组,记录我们要用到的阶乘 int book[12]={0};//标记数组,标记有没有用过 int main(){    string temp;//测试数据     int num;    int now;//仅仅作为一个中间变量用     int res;//结果     int x;//比当前元素小且没有被用过的数量     cin>>num;    while(num--)    {        memset(book,0,sizeof(book));        //初始化结果最小为1         res = 1;        cin>>temp;                for(int i=0;i<12;i++)        {            x = 0;            now = temp[i]-97;            //标记当前的temp[i]已经用过             book[now] = 1;            //开始找比当前的temp[i]小的元素且没有用过的元素有几个             for(int j=0;j<11;j++)            {                if(book[j]==0&&now>j)                    x++;            }                        //找出来的结果 进行相加             res += jc[10-i]*x;        }                cout<<res<<endl;    }    return 0;}

代码解释的很全。个人感觉这种题只是考一个模板,我也不知道康托展开式在算法比赛中有啥用。。希望高手可以告诉我康托展开式可以做啥~

NYOJ 139 我排第几个 康托展开式