HDU6092 子集问题

来源:互联网 发布:电脑监控软件破解 编辑:程序博客网 时间:2024/05/21 10:06

Rikka with Subset

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 380    Accepted Submission(s): 164


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 A1An 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 A1An.

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

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

For each testcase, the first line contains two numbers n,m(1n50,1m104).

The second line contains m+1 numbers B0Bm(0Bi2n).
 

Output
For each testcase, print a single line with n numbers A1An.

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

Sample Input
22 31 1 1 13 31 3 3 1
 

Sample Output
1 21 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]$
 
题意:有一个集合A,里面有一些数,它生成了一个数列B,B与A之间的关系是: 对于Bi ,它指的是集合A里和为 i 的子集个数为Bi  A的长度为 n , B的长度为 m + 1
第一组数据的解释题目已经给出了,顺便说说第二组数据
3  3
1  3  3  1      和为0的子集有一个(空集) 和为1的子集有3个(三个一分别是三个子集) 和为2的子集有三个(3个1两两组合,有三个组合) 和为3的子集就一个(111)
所以答案 1 1 1 是可行的
思路:
题目要求有多组答案的时候要字典序最小,由于下标不会小于0,所以和为0的就只有空集,所以 B0一定是1 ,为了字典序最小,我们从前往后即可,往后看就知道了
对于 B[1] 来说,它只能由单个的数字1组成,所以B[1] = 1的个数,我们一个一个地取出,对于B[2]来说,当你取出了一个1的时候,还剩下X个一没有取出,这两个1就可以分别跟取出的那个1组成 X 个2 ,那么B[2] 就可以减X了,同理后面的B[3] 可以由取出的那个 1 和 剩余的 B[2] 组合成Y个3,那么B[3]就可以减Y了
可能有人会说 那B[2]本来有那么多个,你为什么B[2]减了Y后再去跟那个1组合成3呢,这样是不是组少了。原因是,你这个B[2]减去的那部分是由那个取出来的1组成的
如果你不减就直接去组成3的话,取出来的那个1就重复使用了(又用来了2里,然后这个2又去和这个1组合,那这个1在这个子集里就用了两次),但是它并不能多用。
所以这个状态就是
找到第一个B[I]不为0的下标 id,因为它前面已经没有东西可以组成它了,所以就直接取一个它(这样字典序最小),然后后面的组合方程就是
for(int i = id;i <= m;i++){
B[i] -= B[i - id];
}
#include<stdio.h>#define ll long longint n,m;ll a[10005];int main(){int t,id;scanf("%d",&t);while(t--){scanf("%d %d",&n,&m);for(int i = 0;i <= m;i++){scanf("%lld",&a[i]);}for(int k = n;k >= 1;k--){id = 0;for(int i = 1;i <= m;i++){if(a[i]){id = i;break;}}printf("%d",id);if(k == 1)printf("\n");elseprintf(" ");for(int i = id;i <= m;i++){a[i] -= a[i - id];}}}return 0;}



原创粉丝点击