01背包刷题记录
集合A
对于从1到N (1 <= N <= 39) 的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等的。举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,每个子集合的所有数字和是相等的:
{3} 和 {1,2}
这是唯一一种分法(交换集合位置被认为是同一种划分方案,因此不会增加划分方案总数) 如果N=7,有四种方法能划分集合{1,2,3,4,5,6,7},每一种分法的子集合各数字和是相等的:
{1,6,7} 和 {2,3,4,5} {注 1+6+7=2+3+4+5}
{2,5,7} 和 {1,3,4,6}
{3,4,7} 和 {1,2,5,6}
{1,2,4,7} 和 {3,5,6}
给出N,你的程序应该输出划分方案总数,如果不存在这样的划分方案,则输出0。
分析一下题目,发现此题实际上是求选多个数,和为\(n*(n+1)/4\)的方案数。然后,我没有发现有些情况是没有答案的,即\((n*(n+1)/4)%4 != 0\)的情况下是没有方案的,因为此时求得的所以数的和是无法均分成两半的,所以应该特殊判断,这里没搞好。
然后我考虑状态,发现了子问题,令\(f(m)\) 为和为m的方案数,实际上就是$$\sum_{i = m-n}^{m-1} f(i)$$ 然后这可以转换成01背包。令\(f[0] = 1\)则对于任意的\(j\)和\(1<=k<=n\) 都有\(f[j+k] +=f[j]\)
这样递推一下状态就可以了。
代码实现
组合数
和上一题大同小异,用组合数学的知识可以得到总方案数为\(2^n\)搞一下l到r 所以所有方案数的和,除一下就完事了。
代码实现

浙公网安备 33010602011771号