Subset sequence
Problem Description
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
Solution
我们先来计算一下
An
的子序列有多少,
k
位的子序列有
根据子序列第一位,可以将子系列分为
a=(m−1)/(A[n−1]+1)+1
那么第一位也就得知了,是未使用的数字中第 a 个,并记录这个数字,然后将
(a−1)∗(A[n−k−1]+1)
此时我们需要计算剩下的数字的第
m
个子序列,不过注意此时子序列是可以为空的,因此若Code
#include <stdio.h>
#include <stdlib.h>
long long f(int n)
{
long long sum = 0,sum2 = 1;
while(n)
{
sum2 *= n;
sum += sum2;
n --;
}
return sum;
}
int No(int s[],int k,int n)
{
int i;
for(i=1;i<=n;i++)
if(s[i] == 0)
{
k--;
if(k == 0)
return i;
}
return 0;
}
int main()
{
long long A[25],i,j,k,n,m; // A[i] 记录了A(i,1)+A(i,2)+……+A(i,i)的排列数
for(i=1;i<=20;i++)
A[i] = f(i);
while(scanf("%I64d %I64d",&n,&m) == 2)
{
int v[25],p[25]; // v标记数字是否使用,p记录产生的序列
k = 0;
for(i=1;i<=n;i++)
v[i] = 0; // 标记为未用
while(m)
{
int a = (m-1)/(A[n-k-1]+1) + 1; //
int b = No(v,a,n); // 第a个未使用的数
v[b] = 1;
p[k] = b;
m -= (a-1)*(A[n-k-1]+1);
k ++;
if(m == 1)
break;
else
m --;
}
for(i=0;i<k-1;i++)
printf("%d ",p[i]);
printf("%d\n",p[k-1]);
}
return 0;
}