由逆序列的序号反推出逆序列

题目描述:
给出正整数 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
//

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值