排列的字典序问题
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 }的一个排列,计算出这个排列的字典序值,以及按字典序排列的下一个排列。

给定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;
}