HDU 2062 Subset sequence 数位dp,思路 难度:1

http://acm.hdu.edu.cn/showproblem.php?pid=2062

Subset sequence

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3569    Accepted Submission(s): 1802


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
 
规律:
比如3个的,如果把每种深度视为一大格,那么对于任意深度d(start from 0),
*              第一个一定是空,剩下有n-d个没被使用的数字按照顺序排列,
1              且n-d个数字的小格高度相同
  *        明显,我们可以提前处理出这个高度
  2        第(n-1)层每个数字占1个高度
    *  第(n-2)层每个数字占2个高度,1个空格,1个数字
    3  第(n-3)层每个数字有5个高度,1个空格,2个数字
  3       ......
    *  第i层有:dis[i]=(n-1-i)*dis[i+1]+1
    2  所以 dis[i+1]=(dis[i]-1)/(n-1-i)
2             也就是dis[i]=(dis[i-1]-1)/(n-i)
  *       处理出来之后,一层层查找确定对应位上的数字即可
  1
    *
    3
  3
    *
    1
3
  *
  1
    *
    2
  2
    *
    1
 
#include <iostream>

#include <cstring>

using namespace std;

typedef unsigned long long ll;

int n;

ll m;

int bit[20],len;

bool used[21];

int fnd(int ind){

        int ind2=0;

        for(int i=1;i<21;i++){

                if(!used[i]){

                        if(ind==ind2)return i;

                        ind2++;

                }

        }

        return -1;

}

ll all;

ll dis[21];

int main(){

        while(cin>>n>>m){

                memset(used,0,sizeof(used));

                all =1;

                ll sub=1;

                for(int i=0;i<n;i++){

                        sub*=(n-i);

                        all+=sub;

                }



                for(int i=0;i<n;i++){

                        all--;

                        dis[i]=all/(n-i);

                        all/=(n-i);

                }

                len=0;

                for(int i=n;i>=1;i--,len++){

                        if(m==0){break;}

                        m--;

                        bit[len]=fnd(m/dis[len]);

                        used[bit[len]]=true;

                        m%=dis[len];

                }

                for(int i=0;i<len;i++){

                        cout<<bit[i]<<(i==len-1?'\n':' ');

                }

        }

        return 0;

}

  

你可能感兴趣的:(sequence)