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
题意:给定一个数n,求集合{1~n}的所有的子集按字典序进行排序,而且可以相同,只要顺序不同就可以。
比如n=3,就有:
{1}
{1,2}
{1,3}
{1,2,3}
{1,3,2}
{2}
{2,1}
{2,3}
{2,1,3}
{2,3,1}
{3}
{3,1}
{3,2}
{3,1,2}
{3,2,1}
因此,不难看出,当n=3时,总共有15个,可以分为3组,每组5个,
设给定n子集总数f[n],f[n]=(f[n-1]+1)*n
设每组g[n],g[n]=(n-1)*g[n-1]+1
然后就发现问题转化成了求第一个数字,每次把第一个数求出来后,问题还是求第一个数。
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long c[21];
c[1]=1;
for(int i=2; i<=20; i++)
c[i]=c[i-1]*(i-1)+1;
int d[21],n,t;
long long m;
while(cin>>n>>m)
{
for(int i=1; i<=20; i++)
d[i]=i;//每次循环必须重置
while(n>0&&m>0)
{
t=m/c[n]+(m%c[n]==0?0:1);//每次都求第一个数
if(t>0)
{
cout<<d[t];
for(int i=t; i<=n; i++)
d[i]=d[i+1];//把之前用过的删去
m-=((t-1)*c[n]+1);
putchar(m==0?'\n':' ');
}
n--;
}
}
return 0;
}