题目描述:
给出正整数 n ,则 1 到 n 这 n 个数可以构成 n !种排列。设 i1 … in 是一个排列,则 a1 … an 是它的逆序列,其中 aj 是 j 的左边大于 j 的数的个数。把这些排列按照逆序列从小到大的顺序列出,如 n=3 时,列出 1 2 3 , 1 3 2 , 2 1 3 , 3 1 2 , 2 3 1 , 3 2 1 六个排列,因为它们的逆序列分别是 0 0 0 , 0 1 0 , 1 0 0 , 1 1 0 , 2 0 0 , 2 1 0 。
任务描述:
给出一个数 n 和 k ,求 1 到 n 排列中按逆序列从小到大的顺序下的第 k 个排列。
比如: n = 3 , k=2 ,则答案是 1 3 2 。
#include<iostream>
#include<cstdio>
using namespace std;
const int f[11] = { 0,1,2,6,24,120,720,5040,40320,362880,3628800 };
int main()
{
int z,n,k;
int x[11] = { 0 };
int out[11] = { 0 };
//freopen("in.txt", "r", stdin);
scanf("%d", &z);
while (z--)
{
scanf("%d%d", &n, &k);
k -= 1;
for (int i = n - 1;i > 0;i--)//得到逆序列
{
while(k-x[i]*f[i]>=0)
{
x[i]++;
}
x[i]--;
k -= x[i] * f[i];
}
int flag=0,indicator=0;
for (int i = n - 1;i >= 0;i--)//确定序列的每一个数 的位置
{
while (indicator!=x[i]+1)
{
if (out[flag] == 0) { flag++; indicator++; }
else { flag++;continue; }
}
out[flag-1] = n - i;
flag = 0;indicator = 0;
}
for (int i = 0;i < n-1;i++) printf("%d ", out[i]);
printf("%d\n", out[n - 1]);
memset(out, 0,sizeof(int)*11);
memset(x, 0, sizeof(int)*11);
}
}
//Sample Input
// 3
//
// 3 1
//
// 3 6
//
// 10 100
//
// Sample Output
//
// 1 2 3
//
// 3 2 1
//
// 1 2 3 4 5 7 10 8 9 6
//