题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2062

Problem Description
考虑集合An = {1,2,...,n}。 例如,A1 = {1},A3 = {1,2,3}。 子集序列被定义为非空子集的数组。 按照字典顺序排列An的所有子集。 你的任务是找到第m个。
Input
输入包含多个测试用例。 每个测试用例由两个数字n和m组成(0 <n <= 20,0 <m <= An的子集序列总数)。
Output
对于每个测试用例,您应该在一行中输出An的第m个子集序列。
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
解题思路:题目的意思就是求第m个按字典序排列的子集(非空)。这里我们先找一下规律:假设f(n)为An的子集的总个数,a(n)为An中每组(首元素相同的一组)的子集合个数,则有:

当n=1时,f(1)=1,a(1)=1,有1个子集合:{1};

当n=2时,f(2)=4=2*(f(1)+1),a(2)=2=f(2)/2=f(1)+1,有4个子集合:{1},{1, 2};{2},{2, 1}。

当n=3时,f(3)=15=3*(f(2)+1),a(3)=5=f(3)/3=f(2)+1,有15个子集合: {1}, {1, 2}, {1, 3},{1, 2, 3}, {1, 3, 2};

{2}, {2, 1}, {2, 3}, {2, 1, 3}, {2, 3, 1};{3}, {3, 1}, {3, 2}, {3, 1, 2}, {3, 2, 1}。

由以上规律得知:f(n)=n*(f(n-1)+1),a(n)=f(n)/n=f(n-1)+1,而a(n-1)=f(n-1)/(n-1),所以f(n-1)=(n-1)*a(n-1),

即有a(n)=a(n-1)*(n-1)+1;这就推导出每组(首元素相同的一组)的子集合个数。

下面举个栗子:n=3m=10,m表示求n的第m个子集合,首先我们已经按照推导公式将a数组(求每组的子集合个数)打表,接下来求m是在第几个大组,t=m/a[n]+(m%a[n]>0?1:0)=10/5+0=2,表示此时该集合在第二大组,此时直接输出首元素2,剩余1,3这两个元素,该集合{2,3,1}的位置为m-(t-1)*a[n]=10-(2-1)*5=5,表示在第二大组的第5个集合这个位置,删除集合中有'2'这个元素后,剩余集合按字典序排得到{1},{1,3};{3},{3,1}。此时有两个大组,我们知道,剩下的要求的元素所在集合为第4个位置,n为原来的3个大组减去首元素都为2的这一组后变为2个大组即n=2,执行t那条语句得t=4/2+0=2,则所求当前集合在第2大组的第m-(t-1)*a[n]=4-(2-1)*2=2个位置,即所求集合在所有集合中的位置为m=10-(5+1)=4(还要减去一个空集才得到剩下集合的位置),所以此时输出首元素3,剩下1这个元素,删掉集合中有'3'这个元素后,剩下集合为{1},易知当前位置为1,即所求集合在所有集合中的位置m=4-(2+1)=1n=1,执行t语句后t=1/1+0=1,验证m-(t-1)*a[n]=1-0=1,对应得到接着去掉'3'元素后剩下子集合中的第1大组第1个位置,所以此时输出首元素1,删掉集合中有1这个元素后变成空集,即m=1-(0+1)=0n=0退出循环查找,即得到n=3时的第10个子集合。

结合以上规律,可以得到循环中m=m-(a[n]*(t-1)+1)直到m==0退出,并且每输出一个元素,相应的n大组数减1,直到n==0退出。

这里用s数组按下标给其字典序赋值,当输出每个元素后,后面的元素要往前移一位进行覆盖,因为不用这个元素了,且下次求该组位置的元素刚好对应首元素,这里自己可以模拟一下。

AC代码:

 #include<bits/stdc++.h>
using namespace std;
int main()
{
int n,s[],t;//n表示一共有多少个元素,s是后面将子集按照字典序分组后每组的初始首元素,组数<=20,t是所求子集位于分组后的第几位
long long m,a[]={};//m是位于第几个子集,后面是将子集分组后平均每组的个数,如a[2]表示n=2时的分组每组中子集数
for(int i=;i<;i++)
a[i]=a[i-]*(i-)+;//推导出来的,表示An中每一组的子集合个数
while(cin>>n>>m){
for(int i=;i<;i++)
s[i]=i;//每循环一次就重新归位每组首元素
while(n> && m>){
t=m/a[n]+(m%a[n]>?:);//先记录在第几个大组
if(t>){//得到第m个子集在分组后的第t组,若t>0
cout<<s[t];//先输出该组的首元素
for(int i=t;i<=n;i++)
s[i]=s[i+];//或s[i]+=1,我们发现:第n组中,第2个元素在第n个时变为它的下一个数
m-=((t-)*a[n]+);//m-(t-1组总子集数+1),m表示在剩余子集中位于第几个
putchar(m==?'\n':' ');//m最后为0,直接输出换行,不然就输出空格
}
n--;//减掉删除该首元素的一整组
}
}
return ;
}

题解报告:hdu 2062 Subset sequence的更多相关文章

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

    http://acm.hdu.edu.cn/showproblem.php?pid=2062 Subset sequence Time Limit: 1000/1000 MS (Java/Others ...

  2. HDU 2062 Subset sequence (找规律)

    题目链接 Problem Description Consider the aggregate An= { 1, 2, -, n }. For example, A1={1}, A3={1,2,3}. ...

  3. HDU 2062 Subset sequence

    我是把它当做一道数学题来做的. 这篇题解写的有点啰嗦,但是是我最原始的思维过程. 对于一个集合An= { 1, 2, …, n },在n比较小的情况下,在纸上按字典顺序把所有子集排列一下. 以n=3, ...

  4. hdu(2062)-Subset sequence 组合数学

    意甲冠军:查找集合{1,2,3...n}第一m一个排列子. 收集的线索所行的大小. 例两个元素的排列子集合按字典树排列是:{1},{1,2},{2},{2,1}: 解法:一个一个元素来确定,每次把剩余 ...

  5. 【HDOJ】2062 Subset sequence

    这道题目非常好,饶了点儿圈子.我的思路是,先按照组排列.例如,1            2           31 2         2 1        3 11 2 3      2 1 3  ...

  6. HDU 2062:Subset sequence(思维)

    Subset sequence Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...

  7. 题解报告:hdu 1398 Square Coins(母函数或dp)

    Problem Description People in Silverland use square coins. Not only they have square shapes but also ...

  8. 题解报告:hdu 2069 Coin Change(暴力orDP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2069 Problem Description Suppose there are 5 types of ...

  9. 题解报告:hdu 1028 Ignatius and the Princess III(母函数or计数DP)

    Problem Description "Well, it seems the first problem is too easy. I will let you know how fool ...

随机推荐

  1. 矩阵奇异值分解(SVD)

    转自:https://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html  (感谢,讲解的太好了) 在机器 ...

  2. Oracle 数据库管理员的任务

    设计.实施和维护 Oracle 数据库时,按优先次序排列的任务包括:   1. 确定数据库服务器硬件   2. 安装 Oracle 软件   3. 为数据库和安全策略制定计划   4. 创建.移植和打 ...

  3. 高端技巧:怎样使用#define定义变量

    Introduction 想在源文件里定义一个跟行号有关的变量,每次都手动输入实在是太慢了.本文介绍怎样使用宏定义来定义与行号有关的变量. 比如:我们想在源码的第10行定义A_10这种一个整形变量. ...

  4. 【C】字符串,字符和字节(C与指针第9章)

    C语言没有一种显式的数据类型是字符串的. C语言存储字符串:字符串常量(不能改动).字符数组或动态分配的内存(能够改动) *************************************** ...

  5. Apach POI 如何拿到有公式的单元格,计算结果

    public static void getFormulaCellValue(){ FileInputStream fis = new FileInputStream("c:/temp/te ...

  6. I2C上拉电阻取值范围

    I2C总线是微电子通信控制领域中常用的一种总线标准,具备接线少,控制简单,速率高等优点.在I2C电路中常见的上拉电阻有1k.1.5k.2.2k.4.7k.5.1k.10k等等,但是应该如何根据开发要求 ...

  7. Visual Studio 2012 Fakes框架测试驱动开发TDD教程

    一.前言 最近团队要尝试TDD(测试驱动开发)的实践,很多人习惯了先代码后测试的流程,对于TDD总心存恐惧,认为没有代码的情况下写测试代码时被架空了,没法写下来,其实,根据个人实践经验,TDD并不可怕 ...

  8. Linux 简单的Shell输出

    echo:用于输出指定字符串或用于在Shell中打印Shell变量的值    语法格式:echo [选项] [参数]    -n:不输出换行 linlin@ubuntu:~/linlin/text$ ...

  9. Codeforces 104C Cthulhu dfs暴力 || 点双连通缩点

    题目链接:点击打开链接 题意: 给定n个点m条边的无向图 问图中是否存在 有且仅有一个简单环和一些树,且这些树的root都在这个简单环上. 瞎写了个点双. . == #include <stdi ...

  10. jquery源码学习笔记三:jQuery工厂剖析

    jquery源码学习笔记二:jQuery工厂 jquery源码学习笔记一:总体结构 上两篇说过,query的核心是一个jQuery工厂.其代码如下 function( window, noGlobal ...