您的位置:首页 > 其它

HDU6092 Rikka with Subset-01背包dp-2017多校联盟5 第8题

2017-08-09 19:10 561 查看

Rikka with Subset

[b]Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
[/b]
[align=left]Problem Description[/align]
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?  
 

[align=left]Input[/align]
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).
 

[align=left]Output[/align]
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.
 

[align=left]Sample Input[/align]

2
2 3
1 1 1 1
3 3
1 3 3 1

 

[align=left]Sample Output[/align]

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]$

 

[align=left]Source[/align]
2017 Multi-University Training Contest - Team 5
 

/*
题意:
一个序列a有n个数,和为m,这个序列能组成2^n个子序列,bi表示这些子序列中和为i的个数
现在给你bi,i∈[0,m]求出序列a,a按字典序输出

解题思路
首先能明确的是b[0]一定等于1,并且b中第一个不为0的i一定有b[i]个。
b[i]=i的个数+组合成i的方案数.当确定a中存在i,并且能组合出j-i,那么一定能组合出j,
这种途径得到j的方案数就是j-i的方案数
*/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn = 1e4 + 10;

int dp[maxn];///组合成i的方案数,不包括i本身,(准确的说是在完成第46行循环之前不包括本身。)
int b[maxn];
int n,m;

int main()
{
int t;

scanf("%d", &t);
while (t > 0)
{
t--;
memset(dp,0,sizeof(dp));
dp[0] = 1;
scanf("%d%d",&n,&m);
for(int i = 0;i<=m;++i){
scanf("%d",&b[i]);
}
bool f = 0;
for(int i = 1;i<=m;++i){
int cnt = b[i]-dp[i];///b[i]=i的个数+组成i的方案数dp[i]
if(cnt<=0) continue;///不存在i
for(int k = 0;k<cnt;++k){///a里面肯定有cnt个i
if(f) printf(" ");
f=1;
printf("%d",i);
for(int j = m;j>=i;--j){
dp[j] += dp[j-i];///组成j-i的方案分别加上i就能组成j,加上这种途径获得的方案数
//dp[j+i] += dp[j];一样的也能过,注意j的范围
}
}
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM hdu 多校 dp 背包