用N个硬币计算总和K.

时间:2014-09-15 12:57:39

标签: algorithm

给定N个硬币的面额A [1],A [2] ...... A [n]其中每个A [i]是唯一的,并且它们是每个面额的无限硬币。也可以是最多15种硬币,其意味着N <= 15。

现在我们需要分发这些硬币,使所有分配的硬币的总和变为K. 如果分布顺序不同,则两个分布是不同的,这意味着如果我们需要得到和8,那么2,3,2是与2,2,3不同的分布。

我们需要找到这些分布的数量。

如何以高效的方式完成此操作,因为K可以达到10 ^ 18,尽管N和A [i]都小于或等于15.

示例:设K = 19且N = 2且面额为[4,5],则此处答案为4,因为4种可能的方式为:[5,5,5,4],[5,5,4, 5],[5,4,5,5]和[4,5,5,5]。

方法1:我知道硬币问题,并认为它可以帮助。但不知道如何修改它。

2 个答案:

答案 0 :(得分:1)

C[K]成为总计K的方式数。我们有线性同质复发

C[K] | K <  0 = 0
     | K == 0 = 1
     | K >  0 = sum from j=1 to N of C[K - A[j]].

这不是通常的硬币更换问题的再现,因为这不是通常的硬币更改问题

M = max from j=1 to N of A[j]。然后是矩阵L,对于所有K

L [C[K - 1]] = [C[K]        ]
  [...     ]   [...         ]
  [C[K - M]]   [C[K - M + 1]].

例如,对于A = [1, 3, 4],此矩阵L

[1 0 1 1]
[1 0 0 0]
[0 1 0 0]
[0 0 1 0].

对于A[j]j=1,第一行的列N中有一行(或者,如果存在具有相同值的可区分硬币,则更高的数字)。其他行的主要对角线正下方。

[1 0 1 1] [C[3]] = [C[3]        + C[1] + C[0]] = [C[4]]
[1 0 0 0] [C[2]]   [C[3]                     ]   [C[3]]
[0 1 0 0] [C[1]]   [       C[2]              ]   [C[2]]
[0 0 1 0] [C[0]]   [              C[1]       ]   [C[1]]

要在序列中快速向前跳至K,请使用exponentiation by squaring计算L^K,然后乘以初始条件向量[C[0] ... C[-M + 1]]' = [1 0 ... 0]'并返回第一个条目(即,矩阵幂的左上角。)

答案 1 :(得分:0)

假设K10^18A = [1,2]。只计算[1,1,.....2],[1,1,......2,1]类型的答案,您将需要返回10^18-1这样的数组。因此,我得出的结论是,由于时间和空间的复杂性,通过计算机无法解决的问题,这个问题无法解决。