[英]Count number of subsequences with given k modulo sum
給定n
整數的數組a
,計算有多少個子序列(非連續的)具有sum % k = 0
:
1 <= k < 100
1 <= n <= 10^6
1 <= a[i] <= 1000
O(n^2)
解決方案很容易實現,但需要更快的方式O(n log n)
或O(n)
。
這是子集求和問題。
一個簡單的解決方案是:
s = 0
dp[x] = how many subsequences we can build with sum x
dp[0] = 1, 0 elsewhere
for i = 1 to n:
s += a[i]
for j = s down to a[i]:
dp[j] = dp[j] + dp[j - a[i]]
然后你可以簡單地返回所有dp[x]
的總和,使得x % k == 0
。 這有一個很高的復雜性:約O(n*S)
,其中S
是所有元素的總和。 dp
數組也必須具有大小S
,您可能甚至無法為約束聲明。
更好的解決方案是不首先迭代大於或等於k
的和。 為此,我們將使用2個dp
數組:
dp1, dp2 = arrays of size k
dp1[0] = dp2[0] = 1, 0 elsewhere
for i = 1 to n:
mod_elem = a[i] % k
for j = 0 to k - 1:
dp2[j] = dp2[j] + dp1[(j - mod_elem + k) % k]
copy dp2 into dp1
return dp1[0]
其復雜度為O(n*k)
,並且對於該問題是最佳的。
有一個O(n + k^2 lg n)
時間算法。 計算輸入數組mod k
的直方圖c(0), c(1), ..., c(k-1)
(即,存在作為r
mod k
c(r)
元素)。 然后計算
k-1
product (1 + x^r)^c(r) mod (1 - x^k)
r=0
如下所示,其中簡化多項式的常數項是答案。
我們不是用快速求冪方法評估每個因子然后相乘,而是將內容轉化為內心。 如果所有c(r)
都為零,則答案為1
。 否則,遞歸評估
k-1
P = product (1 + x^r)^(floor(c(r)/2)) mod (1 - x^k).
r=0
然后計算
k-1
Q = product (1 + x^r)^(c(r) - 2 floor(c(r)/2)) mod (1 - x^k),
r=0
通過利用因子的稀疏性,在后面計算的時間O(k^2)
。 結果是P^2 Q mod (1 - x^k)
,通過初始卷積在時間O(k^2)
計算。
遍歷a
並計算a[i] mod k
; 就必須有k
這樣的罪名。
遞歸並記憶k, 2*k, 3*k...etc.
的不同分區k, 2*k, 3*k...etc.
如果零件小於或等於k
,則添加適當數量的產品。
例如,如果k
是10
,則一些分區將是1+2+7
和1+2+3+4
; 但是在記憶時,我們只需要計算一次數組中的mod k
對產生多少(1 + 2)
。
例如, k = 5, a = {1,4,2,3,5,6}
:
counts of a[i] mod k: {1,2,1,1,1}
products of distinct partitions of k:
5 => 1
4,1 => 2
3,2 => 1
products of distinct partitions of 2 * k with parts <= k:
5,4,1 => 2
5,3,2 => 1
4,1,3,2 => 2
products of distinct partitions of 3 * k with parts <= k:
5,4,1,3,2 => 2
answer = 11
{1,4} {4,6} {2,3} {5}
{1,4,2,3} {1,4,5} {4,6,2,3} {4,6,5} {2,3,5}
{1,4,2,3,5} {4,6,2,3,5}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.