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
题目的意思是根据字典序求第m个子集。
如n为1时子集有
{1}
n为2时子集有
{1} {2}
{1,2} {2.1}
n为3时子集有
{1} {2} {3}
{1,2} {2,1} {3,1}
{1,3} {2,3} {3,2}
{1,2,3} {2,1,3} {3,1,2}
{1,3,2} {2,3,1} {3,2,1}
通过观察我们可以发现有n个元素有n * cou[n]个子集,同时每组除了第一项,剩下的是(n-1)个元素组成的集合,那么我们可以推出cou[n] = (n - 1) * cou[n-1] + 1;
为求得m在哪一组我们可以通过tmp = m / cou[n]来计算,若m % cou[n] != 0的话意味着m是第tmp + 1组,因此tmp++。令m -= (tmp - 1) * cou[n] + 1以求得在第n-1的子集中的第几个,循环到n == 0 || m == 0结束
#include<iostream>
using namespace std;
int main() {
int n, arr[21];
long long m, cou[21] = {0}, tmp;
for(int i = 1;i <= 20;i++) {
cou[i] = (i - 1) * cou[i-1] + 1;
}
while(cin >> n >> m) {
for(int i = 1;i <= n;i++) {
arr[i] = i;
}
while(n && m) {
tmp = m / cou[n];
if(m % cou[n] != 0)
tmp++;
cout << arr[tmp];
for(int i = tmp;i < n;i++) {
arr[i] = arr[i+1];
}
m -= (tmp - 1) * cou[n] + 1;
n--;
if(m) {
cout << " ";
}
}
cout << endl;
}
return 0;
}