簡體   English   中英

計算給定k個模和的子序列數

[英]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 ,則添加適當數量的產品。

例如,如果k10 ,則一些分區將是1+2+71+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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM