題幹
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
題解
大神講解的已經很清楚了(走你),我只寫我的總結:
/**
*整個題目的解題關鍵就在於,要學會用一個數組去搞排列組合,通過
*不斷的維護和更新數組(這個題目維護s[]數組),
*並且通過一定的公式(這個題目的公式是第22行和第23行的代碼)計算不斷輸出,
*才能得出最終結果
*總結:
*1,注意變量的類型是否正確,如果沒有給出,則一定要精確確定數據範圍,
*不然WA沒商量,特殊情況下,就算給了變量類型,也可能給的不對,要自己確定清楚
*2,學會通過維護數組+固定公式去搞排列組合
*/
#include<cstdio>
int s[21]={0};
void del(int pos){
for(int i=pos;i<21;i++)s[i]=s[i+1];
}
int main(){
int n;
__int64 m;//題目中沒有給出m的取值範圍,但是,隱含着m是一個64位整數
__int64 f[21]={0,1},g[21]={0,1};
for(int i=2;i<21;i++){
f[i] = i * (f[i-1]+1);
g[i] = f[i]/i;//g[20]是一個64位整數,所以g[]數組應該用64位整數的
//printf("%I64d\n",g[i]);
}
while(~scanf("%d%I64d",&n,&m)){
for(int i=0;i<21;i++)s[i]=i;
__int64 gsize = g[n];
while(m>0&&n>0){
if(m<=f[n]){
int pos = m%gsize ? m/gsize + 1 : m/gsize;
printf("%d",s[pos]);
del(pos);
m = m - (pos-1)*gsize -1;
gsize = g[--n];
putchar(m>0 ? ' ' : '\n');
}
}
}
}