(hdu 6092)2017杭電多校リーグ第5戦-Rikka with Subsetダイナミックプランニング


Rikka with Subset
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 837    Accepted Submission(s): 411
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]$
 

Source
2017 Multi-University Training Contest - Team 5


题目大意:给你数据的数量,以及数据的总和m,还有给你子集中子集和为0-m的子集数量,询问原始数据,按字典序输出。

分析样例
                 n = 2 ,   m = 3  : 原始数据数量有2个,数据总和为3
                 a0 = 1 , a1 = 1 ,  a2 = 1 ,  a3 = 1 :和为1、2、3、4的子集数量都是1个
               子集的数量是2^n,所以子集数量为4,而和为0、1 、2 、 3、 4的子集分别为1 、1 、1 、1,所以原始数据可以为{1 ,2}


解题思路 :我们知道一个n个元素组成的集合的子集数量是2^n,其中有一个是空集,他的子集和为0,所以a0的值一定为1,而题目中说明了原始数据是正整数,所以不可能出现0,所以要简单很多,不需要考虑0的情况,然后我们开始看 a[i]  数组中第一个不为0的数据,即说明从这里开始有数据,即第一个数据我们可以定为 i,确定了一个 值后我们需要将这个数据可以组成的子集的和值给计算出,这里我们使用的是动态规划,动态方程可以为:dp[i+j]+=dp[i],可以计算出和它和它前面的数据的子集和,然后我们将 a[i]-dp[i], 即和值减去组成的新的和值数量,使用一个循环可以得到每一个原始数据,直到所有的a[i]都被减为0,即数据处理完成。

ac代码:
#include 
#include 
#include 
#include 
using namespace std;
#define ll long long
ll a[20005],dp[20005],s[100];//       2 ,       ,  runtime 
int main()
{
	int T,n,m,i,j;
	int sum;
	scanf("%d", &T);
	while(T--)
	{
		sum=0;
		scanf("%d%d",&n,&m);
		for(i=0;i<=m;i++)
		 scanf("%lld",&a[i]);
		 memset(dp,0,sizeof(dp));
		 dp[0]=1;
		for(i=1;i<=m;i++)
		{
			while(a[i]-dp[i])//     a[i]   0 
			{
				s[sum++]=i;//        i,  a[i]  0 
				for(j=m;j>=0;j--)//    i            
				  dp[i+j]+=dp[j];
			}
		}
		printf("%lld",s[0]);
		for(i=1;i

タイトルリンク;クリックしてリンクを開くhttp://acm.hdu.edu.cn/showproblem.php?pid=6092