Subset sequence
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3383 Accepted Submission(s): 1730
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=4,1开头的顺序:(1)(1,2)(1,2,3)(1,2,4)(1,2,3,4)(1,2,4)(1,2,4,3)(1,3)(1,3,2)(1,3,2,4)(1,3,4)......而且是按开头数字从大到小的顺序排列的,也就是说开头是1排列完后,才开始排列2开头的。有一个这样的规律:n=1:1n=2:(1),(1,2) 每组的个数是f(1)+1; !!! 这里面的f(1)是n=1的总个数,下面的也一样。(2),(2,1)n=3:(1),(1,2),(1,2,3),(1,3),(1,3,4) 每组的个数是f(2)+1;(2),(2,1),(),(),(),......一开始用暴力方法不知为什么没过。。。ac代码如下:#include<stdio.h> __int64 f(__int64 n)//n个数可以排列的组合数 { if(n<=1) return n; else return (f(n-1)+1)*n; } int main() { __int64 n,m; __int64 i,j;//循环变量 __int64 k,fnum;//k表示每组个数,fnum表示每组开头数字 __int64 t;//用于输出空格的变量 __int64 a[50]; while(scanf("%I64d%I64d",&n,&m)!=EOF) { t=0; for(i=1;i<=n;i++) a[i]=i; while(m>0) { /*找第一位数字*/ k=f(n-1)+1; fnum=m/k+1; if(m%k==0) fnum--;//第一个数字 if(t>0) printf(" "); printf("%d",a[fnum]);//输出第一位数字 /*把第二位当成第一位继续找*/ for(i=fnum;i<=n;i++) { a[i]=a[i+1];//输出过的就不能再用了 } m-=(fnum-1)*k+1; n--; t++; } printf("\n"); } return 0; }