查找加起来为特定数字倍数的数组子集数

时间:2014-04-08 18:17:13

标签: c++ c algorithm dynamic-programming subset

我有一个长度为N且负整数的数组A.我需要计算这个数组中的子集数量,它们加起来是数字M的倍数(或0(mod M))
例如:

设A = {1,2,8,4,5},M = 9,
然后,有4个这样的子集:

  • {}:空集,对应多个0,
  • {1,8}:对应多个9,
  • {4,5}:对应多个9
  • {1,8,4,5}:对应于倍数18。

我想过生成所有可能的倍数,然后应用动态编程子集和,但约束不允许我这样做。

的约束:
1 =&lt; N <= 10 ^ 5,
1 =&lt; M <= 100,
-10 ^ 9 =&lt;数组的每个条目&lt; = 10 ^ 9

对于这类问题我应采取什么方法?

1 个答案:

答案 0 :(得分:0)

你可以通过动态编程解决这个问题,虽然对于大M是广泛的,对于小M是快的。对于满足0 <= j <= M-1的每个j,并且每个满足0 <0的整数k <1。 k <= N,令f(k,j)为1和k之间的数组元素的子集数,它们相加得到j mod M之和。然后将计数器f(k,j)扩展为f所有j&#39;(k + 1,j&#39;)你只需要在你的序列中取第(k + 1)个元素X并设置f(k + 1,j&#39;)= f(k,j&#39;)+ f(k,j&#39; - X mod M)。当你对每个k迭代满足0&lt; = j&lt; = M-1的所有j然后连续迭代满足0 <= k <= N的所有k时,你将得到你的答案f(N,0) )。总复杂度为O(MN),对于小M,其在N中基本上是线性的,是最优的。