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.
1 1 2 1 2 2 2 3 2 4 3 10
1 1 1 2 2 2 1 2 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;
}