zoukankan      html  css  js  c++  java
  • HDU 6092 Rikka with Subset(递推)

    Rikka with Subset

    2017ACM暑期多校联合训练 - Team 5 1008 Rikka with Subset
    题目链接

    Problem Description
    As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

    Yuta has n positive A1−An and their sum is m. Then for each subset S of A, Yuta calculates the sum of S.

    Now, Yuta has got 2n numbers between [0,m]. For each i∈[0,m], he counts the number of is he got as Bi.

    Yuta shows Rikka the array Bi and he wants Rikka to restore A1−An.

    It is too difficult for Rikka. Can you help her?

    Input
    The first line contains a number t(1≤t≤70), the number of the testcases.

    For each testcase, the first line contains two numbers n,m(1≤n≤50,1≤m≤104).

    The second line contains m+1 numbers B0−Bm(0≤Bi≤2n).

    Output
    For each testcase, print a single line with n numbers A1−An.

    It is guaranteed that there exists at least one solution. And if there are different solutions, print the lexicographic minimum one.

    Sample Input
    2
    2 3
    1 1 1 1
    3 3
    1 3 3 1

    Sample Output
    1 2
    1 1 1
    Hint
    In the first sample, A is [1,2]. A has four subsets [],[1],[2],[1,2] and the sums of each subset are 0,1,2,3. So B=[1,1,1,1]

    题意:
    给定数组b,保存的数组a中的所有子集和的个数,让找个这个数组a,并且按照字典序输出来。

    分析:
    a数组里面除了第一个元素a[0]肯定为1之外(表示空集的个数有且仅有一个),其余的第一次出现的a[i]==j(j!=0),那么就表示i这个数字肯定在a数组中存在,而且为第一个并且为最小的元素,同时将这个数的个数减减(相当于减去单独自己本身一个自己的情况),记录下标i。

    这样循环的往后加a数组的元素下标偏移i个单位,如果此时两个数的个数均不为0,也就意味这后面的那个数,可以由前面这个数构成,然后让当前下标的数减去a[i],得到的那个数减去a[i]的个数,(相当于减去这个数可以由a[i]组合而成的个数)剩下的肯定就是这个数字本身的个数

    就这样循环着往下找

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int a[1100002];
    int b[1100002];
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            for(int i=0;i<=m;i++)
                scanf("%d",&a[i]);
            a[0]=0;
            for(int i=0;i<n;i++)//b[i]数组又n 个数
            {
                int j;
                for(j=1;j<=m;j++)// 找到a[i]数组 第一不为零的 位置,
                    if(a[j]) break;
                a[j]--;//原有减一 相当于取出一个数
                b[i]=j;//则 b数组中 就应该有 一个j
                for(int k=j;k<=m;k++)//把后面的方案数 减去 去掉的那个的方案数
                    if(k+j<=m&&a[k]&&a[k+j])//控制边界,和不存在的情况
                     a[k+j]-=a[k];
            }
            for(int i=0;i<n-1;i++)
                printf("%d ",b[i]);
            printf("%d
    ",b[n-1]);
        }
        return 0;
    }
    
  • 相关阅读:
    IDEA使用 磨刀霍霍向代码
    如何设计一个高可用系统?要考虑哪些地方?
    spring boot 集成apollo 快速指南
    实战_Spring_Cloud
    Spring Boot 入门(十二):报表导出,对比poi、jxl和esayExcel的效率
    「newbee-mall新蜂商城开源啦」1000 Star Get !仓库Star数破千!记录一下
    一个C#开发者重温Java的心路历程
    BeanUtils 如何拷贝 List?
    JVM之JVM的体系结构
    python类中的私有方法
  • 原文地址:https://www.cnblogs.com/nanfenggu/p/7900064.html
Copyright © 2011-2022 走看看