HDU 6092 Rikka with Subset(dp)

http://acm.hdu.edu.cn/showproblem.php?pid=6092

题意:

给出两个数组A和B,A数组一共可以有(1<<n)种不同的集合组合,B中则记录了每个数出现的次数,现在要根据B数组来推出A数组最小的序列。

 

思路:

如果$B_{i}$是 数组中除了$B_{0}$ 以外第一个值不为 0 的位置,那么显然 i 就是 A 中的最小数。

那么我们每次取出$B_{i}$一个数,对于后面的数组来说,满足$B_{j}=B_{j}-B_{j-i}$,为什么?

其实仔细想想就可以了,比如现在取出的i为2,那么$B_{5}$的方案数是不是可以通过$B_{3}$加上2来合成,所以这也就是上面的式子了。

 1 #pragma comment(linker, "/STACK:102400000,102400000")
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<sstream>
 7 #include<vector>
 8 #include<stack>
 9 #include<queue>
10 #include<cmath>
11 #include<map>
12 #include<set>
13 using namespace std;
14 typedef long long ll;
15 typedef pair<int,ll> pll;
16 const int INF = 0x3f3f3f3f;
17 const int maxn=1e4+5;
18 
19 int n, m;
20 ll a[60];
21 ll b[maxn];
22 
23 int main()
24 {
25    //freopen("in.txt","r",stdin);
26    int T;
27    scanf("%d",&T);
28    while(T--)
29    {
30        int cnt=0;
31        scanf("%d%d",&n,&m);
32        for(int i=0;i<=m;i++)  scanf("%I64d",&b[i]);
33        for(int i=1;i<=m;i++)
34        {
35            if(b[i])
36            {
37                a[++cnt]=i;
38                for(int j=i;j<=m;j++)
39                {
40                    b[j]-=b[j-i];
41                }
42                i--;
43            }
44        }
45        for(int i=1;i<=cnt;i++)
46        {
47            printf("%d",a[i]);
48            if(i!=cnt)   printf(" ");
49            else printf("\n");
50        }
51    }
52    return 0;
53 }

 

posted @ 2017-08-08 21:19  Kayden_Cheung  阅读(166)  评论(0编辑  收藏  举报
//目录