杭电2062

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

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


Author
LL

题首先我们来看看An一共有多少个子集。 
n=1时,只有{1}一个子集合 
n=2时,就有: 
{1},{1, 2}, 
{2},{2, 1} 
4个子集合。 
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}

也许你发现规律了。An子集合的个数为: 
C1n·A11 + C2n·A22 + … + Cnn·Ann 
仔细分析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} 
不难发现,An可以按首数字分成n组,而每组里除了第一项,剩下的就是An-1的子集合了。 
∴f(n) = n[f(n-1) + 1] 
f(1) = 1 
我们拿测试数据3 10来做个示范,解释一下怎么求解。 
因为n=3,所以开始数组里1、2、3三个数。 
我们知道,n=2时,有4种排列,所以上面n=3可以分成三组,每组5个(加上空集)。 
因此第10个在第二组里。所以第一个是2,把2输出。原来的数组里删除2,变成1、3两个数。然后10 - (2 - 1) * 5 = 5,即它在第2组的第5个。 
减去首个空集合,5 - 1 = 4 ≠ 0,表示2后面还有数字。 
因为A1 = 1是,所以再第2组里又可以分成两组,每组2个(加上空集)。 
所以,4在第2组,剩下的数组中,第二个元素是3,所以输出3。再把数组里的3删除,剩下1一个数。 
然后4 - (2 - 1) * 2 = 2,既它是第2组的第2个。 
减去首个空集,2 - 1 = 1 ≠ 0,表示2后面还有数字。 
按上面的方法继续下去,直到n = 0 或 后面为空集为止。 
最后输出数组里的第1个元素,就得到2 3 1,就是解了。 
从上面的计算可以看出来,本题目的关键是先求的An中每一组的个数g(n) 
不难得出:g(n) = f(n) / n 
∵f(n) = n[f(n-1) + 1] 
∴g(n) = n[f(n-1) + 1] / n = f(n-1) + 1 
∵f(n-1) = (n-1) * g(n-1) 

∴g(n) = (n-1) * g(n-1) + 1

[cpp]  view plain  copy
  1. /*Subset sequence 
  2. Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) 
  3. Total Submission(s): 3183    Accepted Submission(s): 1652 
  4.  
  5. Problem Description 
  6. 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.  
  7. Sort all the subset sequece of An in lexicography order. Your task is to find the m-th one. 
  8.  
  9. Input 
  10. 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  
  11. sequence of An ). 
  12.   
  13. Output 
  14. For each test case, you should output the m-th subset sequence of An in one line. 
  15.  
  16. Sample Input 
  17. 1 1 
  18. 2 1 
  19. 2 2 
  20. 2 3 
  21. 2 4 
  22. 3 10 
  23.   
  24.  
  25. Sample Output 
  26. 1 
  27. 1 
  28. 1 2 
  29. 2 
  30. 2 1 
  31. 2 3 1 
  32.   
  33.  
  34. Author 
  35. LL 
  36.   
  37.  
  38. Source 
  39. 校庆杯Warm Up  
  40. */  
  41. #include<stdio.h>  
  42. int main()  
  43. {  
  44.     __int64 i, j, k, m, n, a[22], out, len[22];  
  45.     len[1] = 1;  
  46.     for(i = 2; i < 21; i++)  
  47.         len[i] = (i-1) * len[i-1] + 1;//对于每个n 以1~n为开头的序列数的组数是一样的 所以可以求出每个数的组数   
  48.     while(scanf("%I64d%I64d", &n, &m) != EOF)  
  49.     {  
  50.         for(i = 1; i < 21; i++)// 刚开始时每个i的对应位置都为i  随着i被取走,i位置后的值需要往前移   
  51.         a[i] = i;  
  52.         while( m)  
  53.         {  
  54.             k = (m-1)/len[n] + 1;//求输出中的每个位置的数   
  55.             printf("%I64d", a[k] );  
  56.             for(j = k; j < 21; j++)//输出后更新数组中的值   
  57.             a[j] = a[j+1];  
  58.             m %= len[n];//每次还要更新输出中的下一个位置的位置   
  59.             if(m == 0)  
  60.             m = len[n];  
  61.             m--;  
  62.             n--;//输出一个数减一个   
  63.             if(m)  
  64.             printf(" ");  
  65.             else   
  66.             printf("\n");   
  67.         }  
  68.     }  
  69.     return 0;  
  70. }   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值