HDU 2062:Subset sequence(思维)

Subset sequence

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8188 Accepted Submission(s): 3735

Problem Description

Consider the aggregate An= { 1, 2, …, n }. For example, A1={1}, A3={1,2,3}. A subset sequence is defined as a array of a non-empty subset. Sort all the subset sequece of An in lexicography order. Your task is to find the m-th one.

Input

The input contains several test cases. Each test case consists of two numbers n and m ( 0< n<= 20, 0< m<= the total number of the subset sequence of An ).

Output

For each test case, you should output the m-th subset sequence of An in one line.

Sample Input

1 1
2 1
2 2
2 3
2 4
3 10

Sample Output

1
1
1 2
2
2 1
2 3 1

题意

对于一个序列An={1,2,3...n}A_n=\{1,2,3...n\}A1={1},A3={1,2,3}A_1=\{1\},A_3=\{1,2,3\},我们称一个非空子集元素的排列为一个子集序列。对所有的子集序列按字典顺序排序。求出第m个子序列

思路

首先要求出AnA_n有多少子集:
n=1n=1时,子集个数为1个
n=2n=2时,子集个数为4个
n=3n=3时,子集个数为15个
子集的个数满足F(n)=(F(n1)+1)×nF(n)=(F(n-1)+1)\times n
n=3n=3为例,将AnA_n全部列出来可得:
{1},{1,2},{1,2,3},{1,3},{1,3,2}\{1\},\{1,2\},\{1,2,3\},\{1,3\},\{1,3,2\}
{2},{2,1},{2,1,3},{2,3},{2,3,1}\{2\},\{2,1\},\{2,1,3\},\{2,3\},\{2,3,1\}
{3},{3,1},{3,1,2},{3,2},{3,2,1}\{3\},\{3,1\},\{3,1,2\},\{3,2\},\{3,2,1\}
例如:
在计算样例3 10时,先计算第10个子集位于第几行(以哪个数字开头)。输出该数字后,把该数字从AnA_n中删除,然后删掉第二行之前的所有子集,和第二行的第一个子集{2}\{2\}mm变成在剩余集合中的子集的位置。重复操作,至到mm小于0为止

AC代码

/*
* @Author: WZY
* @School: HPU
* @Date:   2018-11-11 15:02:40
* @Last Modified by:   WZY
* @Last Modified time: 2018-11-11 16:06:05
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <limits.h>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <string>
#include <time.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
#define pi acos(-1.0)
#define INF 0x7f7f7f7f
#define lson o<<1
#define rson o<<1|1
#define bug cout<<"---------"<<endl
#define debug(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<"\n"
const double E=exp(1);
const ll maxn=1e6+10;
const int mod=1e9+7;
using namespace std;
// F[n]=(F[n-1]+1)*n
// 计算n对应的子集的个数
ll F(ll n)
{
	if(n<=1)
		return n;
	return (F(n-1)+1)*n;
}
int main(int argc, char const *argv[])
{
	ios::sync_with_stdio(false);
	#ifndef ONLINE_JUDGE
	    freopen("in.txt", "r", stdin);
	    freopen("out.txt", "w", stdout);
	    double _begin_time = clock();
	#endif
	ll n,m;
	ll a[30];	
	while(cin>>n>>m)
	{
		for(int i=1;i<30;i++)
			a[i]=i;
		int flag=0;
		while(m>0)
		{
			ll k=F(n-1)+1;	//记录每行有多少个集合
			int res=m/k+1;	//记录在第几行
			if(m%k==0)		//在上一行
				res--;
			if(flag)
				cout<<" ";
			cout<<a[res];
			for(int i=res;i<=n;i++)
				a[i]=a[i+1];
			m-=k*(res-1)+1;
			n--;
			flag++;
		}
		cout<<endl;
	}
	#ifndef ONLINE_JUDGE
	    double _end_time = clock();
	    printf("time = %lf ms.", _end_time - _begin_time);
	#endif
	return 0;
}
posted @ 2018-11-12 12:22  友人-A  阅读(279)  评论(0编辑  收藏  举报