zoukankan      html  css  js  c++  java
  • HDU 2062 Subset sequence(思维,数学)

    Subset sequence

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

    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
    
    
    Author
    LL
    

    题首先我们来看看An一共有多少个子集。
    n=1时,只有{1}一个子集合
    n=2时,就有:
    {1},{1, 2},
    {2},{2, 1}
    4个子集合。
    n=3时,有
    {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}

    也许你发现规律了。An子集合的个数为:
    C1n·A11 + C2n·A22 + … + Cnn·Ann
    仔细分析n=3时,有
    {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}
    不难发现,An可以按首数字分成n组,而每组里除了第一项,剩下的就是An-1的子集合了。
    ∴f(n) = n[f(n-1) + 1]
    f(1) = 1
    我们拿测试数据3 10来做个示范,解释一下怎么求解。
    因为n=3,所以开始数组里1、2、3三个数。
    我们知道,n=2时,有4种排列,所以上面n=3可以分成三组,每组5个(加上空集)。
    因此第10个在第二组里。所以第一个是2,把2输出。原来的数组里删除2,变成1、3两个数。然后10 - (2 - 1) * 5 = 5,即它在第2组的第5个。
    减去首个空集合,5 - 1 = 4 ≠ 0,表示2后面还有数字。
    因为A1 = 1是,所以再第2组里又可以分成两组,每组2个(加上空集)。
    所以,4在第2组,剩下的数组中,第二个元素是3,所以输出3。再把数组里的3删除,剩下1一个数。
    然后4 - (2 - 1) * 2 = 2,既它是第2组的第2个。
    减去首个空集,2 - 1 = 1 ≠ 0,表示2后面还有数字。
    按上面的方法继续下去,直到n = 0 或 后面为空集为止。
    最后输出数组里的第1个元素,就得到2 3 1,就是解了。
    从上面的计算可以看出来,本题目的关键是先求的An中每一组的个数g(n)
    不难得出:g(n) = f(n) / n
    ∵f(n) = n[f(n-1) + 1]
    ∴g(n) = n[f(n-1) + 1] / n = f(n-1) + 1
    ∵f(n-1) = (n-1) * g(n-1)
    ∴g(n) = (n-1) * g(n-1) + 1

    #include <bits/stdc++.h>
    using namespace std;
    
    int main()
    {
        int n,a[25];
        long long int m,c[25];
        memset(c,0,sizeof(c));///保存以n开头的数字的排列数目
        for(int i=1;i<=25;i++)
            c[i] = (i-1)*c[i-1]+1;
        while(~scanf("%d %lld",&n,&m))
        {
            for(int i=1;i<=n;i++)///初始化
                a[i] = i;
            while(n>0&&m>0){
                int temp = (m-1)/c[n] + 1;///计算在第几组
                if(temp>0){
                    printf("%d",a[temp]);///在第几组就输出几
                    for(int i = temp;i <= n;i ++){///删掉这个数字
                        a[i] = a[i+1];
                    }
                    m = m-((temp-1)*c[n]+1);///判断在这一组的第几项
                    printf(m==0?"
    ":" ");
                }
                n--;
            }
    }    
    return 0;
    }
    
  • 相关阅读:
    10 个深恶痛绝的 Java 异常。。
    为什么公司宁愿 25K 重新招人,也不给你加到 20K?原因太现实……
    推荐一款代码神器,代码量至少省一半!
    Spring Cloud Greenwich 正式发布,Hystrix 即将寿终正寝。。
    hdu 3853 LOOPS(概率 dp 期望)
    hdu 5245 Joyful(期望的计算,好题)
    hdu 4336 Card Collector(期望 dp 状态压缩)
    hdu 4405 Aeroplane chess(概率+dp)
    hdu 5036 Explosion(概率期望+bitset)
    hdu 5033 Building (单调栈 或 暴力枚举 )
  • 原文地址:https://www.cnblogs.com/nanfenggu/p/7899990.html
Copyright © 2011-2022 走看看