Subset sequence
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4561 Accepted Submission(s): 2212
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时
{1}一个子集合
n=2时
{1}, {2},
{1, 2}, {2, 1}4个子集合。
n=3时
{1}, {2}, {3},
{1, 2}, {1, 3}, {2, 1}, {2, 3}, {3, 1}, {3, 2},
{1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2}, {3, 2, 1}
也可以写成;
n=3时,有
{1}
{1, 2}
{1, 2, 3}
{1, 3}
{1, 3, 2}
{2}
{2, 1}
{2, 1, 3}
{2, 3}
{2, 3, 1}
{3}
{3, 1}
{3, 1, 2}
{3, 2}
{3, 2, 1}
代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i,n;//元素个数;
int t;//所求子集位于分组后的第几组;
int s[25];//后面将子集按字典序分组后每组的初始首元素;
__int64 m;//位于第几个子集;
__int64 c[25]={0};//c[i]表示n=i时的分组每组中子集数;
for(i=0;i<25;i++)
{
c[i]=c[i-1]*(i-1)+1;//c[n]=(n-1)*c[n-1]+1;
}
while(scanf("%d%I64d",&n,&m)!=EOF)
{
for(i=0;i<25;i++)
{
s[i]=i;//每循环一次就重新归位每组首元素;
}
while(n>0&&m>0)
{
t=m/c[n]+1;
if(m%c[n]==0)
t--;
if(t>0)//得到第m个子集在分组后的第t组
{
printf("%d",s[t]);
for(i=t;i<=n;i++)
{
s[i]=s[i+1];//在第n组中,第2个元素在第n个时变为它的下一个数
}
m=m-((t-1)*c[n]+1);//m变为表示在剩余子集中位于第几个
printf(m==0?"\n":" ");
}
n--;//n依次递减,直到执行上面的if代码或退出
}
}
return 0;
}