J - Subset sequence

来源:互联网 发布:淘宝靠谱的香港代购店 编辑:程序博客网 时间:2024/06/16 21:03

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 12 12 22 32 43 10
Sample Output
111 222 12 3 1

该题意思是找M-th的序列并输出。

首先理解题目中排序规则,以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

按照数字大小顺序排序,

可以发现,输出的序列第一个是m除以n个数的排序数,比如2有2种组合,3每次有5种组合,如果组合数以数组a(n)表示,则有a(n)=(n-1)*a(n-1)+1的规律

剩下的依序输出,比如输入的n和m是3 10,则第一个输出的应当是10/5,考虑到3有5种组合,但是第五种是以1开头的最后一种序列,所以,m=10时,其实是2开头的最后一种序列。若是m=11,虽然m/5=2,但是已经是3开头的序列了,所以,计算第一个输出的数时,应该是t=m/n组合数+m%n组合数?1:0;意思是如果求余不为0,加一,这样就符合实际情况。以此类推,每当输出一个t,应当将t从常数数组内去除,也就是将t之后的数全部提前一位。

代码实现如下,C++

#include <iostream>using namespace std;int main(){long long int n, m;long long int p[21], a[22];p[0] = 0, p[1] = 1;for (int i = 2; i < 21; i++)p[i] = p[i - 1] * (i - 1) + 1;while (cin >> n >> m){for (int i = 0; i <= 21; i++)a[i] = i;while (m > 0 && n > 0){int t = m / p[n] + (( m % p [n] ) ? 1 : 0);cout << a[t];for (int i = t; i <= n; i++)a[i] = a[i + 1];m -= ((t - 1)*p[n] + 1);if (m)cout << " ";n--;}cout << endl;}return 0;}




0 0