hdu 6092

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

题意:有两个数组,分别为A数组和B数组,其中B数组是由A数组的子集的和构成的,B[i]代表A在子集的和为i的有多少个,且A,B都是个多重集,也就是说集合里面一个元素可能有多个

思路:因为B数组里面是A的子集的和,那么B数组第一个存在的元素的位置,这个一定代表A里面i元素有B[i]个,因为没有比i要小的元素了。

然后最开始想的是分解,把所有的元素分解成可以由哪些前面的数字的组合构成,然后觉得这样复杂度太高了,你每一个都要递归去找他的和因子,很明显这样不行

然后看了一下官方题解,是用DP,反向的DP,这个思路确实是没有想到过的(其实还是太菜),感觉很巧妙

就是一个B[i] -= B[i-j],j代表当前的A的和,为什么会这样呢

因为B[I-J]代表什么,说明你用B[i-j]+B[j]可以构成一个B[I],减去B[i-j]就是代表减去了用这个i-j这个数构成的情况。

那么最后剩下来的就是代表着B[I]这个数的个数,代表这个数不是由其他因子合成的个数。

最后,我用java写,发现超时,然后用c++的cin输入还是超时,改scanf就可以了

对这些东西还是不熟啊,java好的输入模板也没有

 

 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7 
 8         int t, m, n;
 9         int locy;
10         long long num[10005];
11         scanf("%d", &t);
12         while ((t--) > 0)
13         {
14             scanf("%d%d", &n, &m);
15             for (int i = 0; i <= m; i++)
16                 scanf("%lld",&num[i]);
17             for (int i = 1; i <= n; i++)
18             {
19                 locy = 0;
20                 for (int j = 1; j <= m; j++)
21                     if (num[j] != 0)
22                     {
23                         locy = j;
24                         break;
25                     }
26                 for (int j = locy; j <= m; j++)
27                     num[j] -= num[j - locy];
28                 if (i != n)
29                     printf("%d ", locy);
30                 else
31                     printf("%d\n", locy);
32             }
33     }
34     return 0;
35 }

 

posted @ 2017-08-09 10:37  一个_小菜鸟  阅读(367)  评论(0编辑  收藏  举报