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;
}

  

时间: 2024-10-04 18:46:51

HDU 2062 Subset sequence 数位dp,思路 难度:1的相关文章

HDU 2062 Subset sequence

我是把它当做一道数学题来做的. 这篇题解写的有点啰嗦,但是是我最原始的思维过程. 对于一个集合An= { 1, 2, …, n },在n比较小的情况下,在纸上按字典顺序把所有子集排列一下. 以n=3,m=10举例: 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 n=3的情况 容易看出前5个打头的是1,紧接着5个子集打头的是2,最后5个开头的是3. 拿前五个来说,除了第一个,后面四个不看开头的1,后面的排列形式和

hdu(2062)-Subset sequence 组合数学

题意:求集合{1,2,3...n}的第m个排列子集合.集合的大小按字典树排. 例两个元素的排列子集合按字典树排列是:{1},{1,2},{2},{2,1}: 解法:一个一个元素来确定,每次把剩余的元素按大小顺序排列在num中,然后根据排列组合原理直接计算下一个位置的元素的大小,直到排列数为0停止: 代码: /****************************************************** * author:xiefubao **********************

hdu 2062 Subset sequence【有点康拓展开的意思】

Subset sequence Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3441    Accepted Submission(s): 1740 Problem Description Consider the aggregate An= { 1, 2, -, n }. For example, A1={1}, A3={1,2,

hdu 3555 Bomb(数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题目大意:就是给你一个数n,判断从0到n有多少个数含有数字49...... 是不是觉得跟hdu2089很相似呀... 思路:跟hdu2089一样的,注意给出的数比较大,所以这儿用__int64  .... code: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm&

[ACM] hdu 2089 不要62(数位Dp)

不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 19043    Accepted Submission(s): 6442 Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就

HDU - 3555 Bomb (数位DP)

题意:求1-n里有多少人包含"49"的数字 思路:数位DP,分三种情况:到第i位没有49的情况,到第i位没有49且最高位是9的情况,到第i位有49的情况,将三种情况都考虑进去就是了 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; long long dp[30][3], n; int arr

HDU 4722 Good Numbers (数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4722 思路:数位dp,dp[i][j]表示到第i位,数字和%10为j,然后进行dp,注意完全匹配的情况是要+1,而其他情况是从0 到 9 都要考虑 代码: #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; int

HDU 2089 不要62(数位DP,三种姿势)

HDU 2089 不要62(数位DP,三种姿势) ACM 题目地址:HDU 2089 题意: 中文题意,不解释. 分析: 100w的数据,暴力打表能过 先初始化dp数组,表示前i位的三种情况,再进行推算 直接dfs,一遍搜一变记录,可能有不饥渴的全部算和饥渴的部分算情况,记录只能记录全部算(推荐看∑大的详细题解Orz) 代码: 1. 暴力 (以前写的) /* * Author: illuz <iilluzen[at]gmail.com> * File: 2089_bf.cpp * Create

HDU 4518 ac自动机+数位dp

吉哥系列故事--最终数 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 304    Accepted Submission(s): 102 Problem Description 在2012年腾讯编程马拉松比赛中,吉哥解决了一道关于斐波那契的题目,这让他非常高兴,也更加燃起了它对数学特别是斐波那契数的热爱.现在,它又在思考一个关于斐波那契