排列的字典序问题

排列的字典序问题

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

n个元素{1,2,……, n }有n!个不同的排列。将这n!个排列按字典序排列,并编号为0,1,…,n!-1。每个排列的编号为其字典序值。例如,当n=3时,6 个不同排列的字典序值如下: 

 
给定n以及n个元素{1,2,……, n }的一个排列,计算出这个排列的字典序值,以及按字典序排列的下一个排列。

Input

输入数据的第1行是元素个数n(n≤20)。接下来的1行是n个元素{1,2,……, n }的一个排列。

Output

输出数据的第1行是字典序值,第2行是按字典序排列的下一个排列。

Sample Input

8
2 6 4 5 8 1 7 3

Sample Output

8227
2 6 4 5 8 3 1 7

Hint

思路:

分两步:

一、计算字典值。

 我们可以从从开始算,因为不能有重复,以1开头的后面有7位数有1*7!,然后以2开头的后面有六位数,但第二位要小于6,即有1、3、4、5满足,有4*6!,然后以26...开头的后面有5位数,要求第三位要小于4,即有1,3满足,有2*5!,,,依次类推。。。
       

看例子:

tot=0;

比2小的数有1个,则 tot+=1*7!;

比6小的数有4个,则 tot+=4*6!;

比4小的数有2个,则 tot+=2*5!;

比5小的数有2个,则 tot+=2*4!;

比8小的数有3个,则 tot+=3*3!;

比1小的数有0个,则 tot+=0*2!;

比7小的数有1个,则 tot+=1*1!;

比3小的数没有;

(注:在排列中,求比某个数小的数的个数时,排除之前出现过的数)

 

二、下一个排列。


从数组最后找,找到一个比最后一个数小的数把最后一个数放在之前就可以了

 

可以用   next_permutation(order,order+n);   来求下一个排列,注意开头 加上 

#include<algorithm>
using namespace std;


#include<iostream>
#include <bits/stdc++.h>

using namespace std;

int main()
{
    int jc[21];
    //先算阶乘
    jc[0]=1;
    for(int i=1;i<21;i++)
        jc[i]=jc[i-1]*i;
    
    int n,sum=0,*a,t;
    //n是多少个数,sum是字典序值,a是数组,t是比当前数小的数的个数

    while(cin>>n)
    {
        a=new int[n+1];
        for(int i=0;i<n;i++)//输入数据
            cin>>a[i];
        for(int i=0;i<n-1;i++)
        {
            t=a[i]-1;//比a[i]小的数最多有a[i]-1个
            //循环找前面,如果前面有比当前数小的数,后面比他小的数就少一个
            for(int j=0;j<=i;j++)
            {
                if(a[i]>a[j])
                    t--;
            }
            sum+=t*jc[n-i-1];//计算当前排列数,累加
        }
        cout<<sum<<endl;
        next_permutation(a,a+n);
        for(int i=0;i<n;i++)
            cout<<a[i]<<" ";
        cout<<endl;

    }
    return 0;

}


猜你喜欢

转载自blog.csdn.net/matrix97/article/details/79951483