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]$
启发博客:http://www.cnblogs.com/stepping/p/7324970.html
官方题解:
1008 Rikka with Subset
签到题,大致的思想就是反过来的背包。
如果 B?i?? 是 B 数组中除了 B?0?? 以外第一个值不为 0 的位置,那么显然 i 就是 A 中的最小数。
现在需要求出删掉 i 后的 B 数组,过程大概是反向的背包,即从小到大让 Bj-=B?(j−i)??。
时间复杂度 O(nm)。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 #include<cmath> 7 #include<string> 8 #include<map> 9 #include<vector> 10 using namespace std; 11 12 int b[10005];//最终结果b 13 int bb[10005];//目前得出的b 14 int a[10005]; 15 16 int main() 17 { 18 int T,n,m,ans; 19 scanf("%d",&T); 20 while(T--) 21 { 22 scanf("%d%d",&n,&m); 23 for(int i=0;i<=m;i++) 24 scanf("%d",&b[i]); 25 memset(a,0,sizeof(a)); 26 memset(bb,0,sizeof(bb)); 27 bb[0]=1; 28 for(int i=1;i<=m;i++) 29 { 30 a[i]=b[i]-bb[i]; 31 for(int j=1;j<=a[i];j++)//对bb进行更新 32 { 33 for(int k=m;k>=i;k--)//反着来避免已经加到结果里的数字再加一遍 34 bb[k]+=bb[k-i]; 35 } 36 } 37 int flag=0; 38 for(int i=1;i<=m;i++) 39 for(int j=1;j<=a[i];j++) 40 { 41 if(flag++) printf(" "); 42 printf("%d",i); 43 } 44 printf("\n"); 45 } 46 return 0; 47 }