HDUOJ 2062 Subset sequence
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
题目的意思简单来说就是:给出一个N代表有一个集合,集合有1~N中的数字组成。集合的所有子集,
非空集,按照字典序排序,给出一个M,求第M个集合的元素。
看了好多歌题解才明白意思,这个大佬讲的还挺清楚
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int ans[50];
long long power[30];
long long num[30]; //num[i]用来记录N个数的时候有多少个子集
int vis[30];
int cnt;
void solve(int N,long long M) {
cnt = 0;
memset(vis,0,sizeof(vis));
int rest = N;
while(true) {
//cout<<"M = "<<M<<endl;
int temp = M/num[rest]; ///计算答案在第几组
if(M%num[rest] != 0)
temp++;
int ccount = 0;
for(int i = 1; i <= N; i++) {
if(vis[i]==0) {
ccount++;
if(ccount == temp) {
vis[i] = 1;
ans[cnt++] = i;
rest--; ///数字减少一个
break;
}
}
}
M = M-(temp-1)*num[rest+1]; ///计算它是该组的第几个
M--;
if(M == 0)
break;
}
}
int main() {
int N;
long long M,Mul = 1;
power[0] = 1;
for(int i = 1; i <= 20; i++) {
power[i] = Mul*i;
Mul = Mul*i;
}
for(int i = 1; i <= 20; i++) {
num[i] = 0;
for(int j = 1; j <= i; j++) {
num[i] = num[i] + power[i]/power[i-j];
}
num[i] = num[i]/i;
}
while(~scanf("%d%lld",&N,&M)) {
solve(N,M);
printf("%d",ans[0]);
for(int i = 1; i < cnt; i++) {
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}