问题在于:
给定一组整数k > 1
和另一个整数A
,是否可以将x
分成两个子集,其总和分别为y
和(x - y) mod k = 0
,其中O(2^N)
很明显,通过列出所有可能的分区,存在时间复杂度count
算法,但是有更高效的分区吗?或者这相当于subset sum problem?
答案 0 :(得分:3)
这实际上相当于子集和,并且可以使用DP解决方案有效地解决(伪多项式时间),因为您的数字是整数。
一个简单的解决方案是使用子集sum的动态规划解决方案:
D(0,i) = true i >= 0
D(x,0) = false x != 0
D(x,i) = D(x-arr[i],i-1) OR D(x,i-1)
通过构建DP表(自下而上的解决方案),完成后您需要做的就是检查是否有x
这样:
D(x,n) = true, abs(x-(SUM-x)) % k = 0
Where:
n - number of elements
SUM = arr[1] + arr[2] + ... + arr[n]
k - the given integer for mod
(x-y) % k = (x-(SUM-x)) % k
但是,对于较小的k
值,您可以将其优化为O(n*k)
(而非O(n*SUM)
。这仍然是伪多项式时间,但如果{{ {1}}。
首先请注意k << SUM
,并且您正在寻找一个总和为x-y = x-(SUM-x) = 2x-SUM
的子集,以便x
。
一个简单的优化是仅对大小2x - SUM % k = 0
执行DP表,如下所示:
(k+1) * (n+1)
上述情况属实,因为D(0,i) = true i >= 0
D(x,0) = false x != 0
D(x,i) = D((x-arr[i])%k,i-1) OR D(x,i-1)
(其中负数的%k被定义为complementary modulus。
现在,当您完成设置表格后,您可以搜索是否有(a-b)%k = (a%k - b%k)%k
x
。这是有效的,因为对于总和为((2x)%k - SUM%k) %k == 0
的每个子集:
t