python - 每 k 圈更换计数

标签 python algorithm combinatorics

问题如下:您有n 种类型的项目,您想要选择其中的l 种(顺序很重要)。仅当自上次选择该项目后选择了 k 个其他项目时,您才可以对该类型的项目重新采样。计算您可以形成的项目序列总数。如果这令人困惑,下面的示例将解决问题:

假设 n = 5l = 6k = 3

答案是5 * 4 * 3 * 2 * 2 * 2。 在第一回合,我们可以选择 5 个项目中的任何一个。在第二、第三和第四轮,我们可以再次选择 432 剩余项目中的任何一个。然后,在第 5 轮我们可以选择 1,但也可以再次选择 5,因为自上次选择后还选择了 3 个其他项目,依此类推。所以总计数是 480

这里有一个简单的算法来解决这个问题:

def differentPlaylists(n, k, l):
    ans, choices = 1, n
    while l > 0:
        ans = (ans * choices) % 1000000007
        choices -= 1
        k, l = k - 1, l - 1
        if k < 0: choices += 1
    return ans

这可行,但速度太慢。我想不通如何生成一种算法,用少于 l 乘法操作来解决这个问题。

谁能帮我弄清楚我该怎么做?

最佳答案

看来您只需要确切数字的余数。答案是:
(n!/(n-k)! * (n-k)^(l-k)) % M = (((n!/(n-k)!) % M) * ((n-k)^(l-k) % M)) % M

您不需要循环来查找(n-k)^(l-k) % M,您可以使用exponentiation by squaringO(log(l-k)) 中有效。如果 k 足够小,它将使整体计算速度显着加快,因为此公式的第一个阶乘部分是在您的解决方案中以 O(k) 计算的。因此,在您的实现中,复杂度为 O(log(l-k)) + O(k) 而不是 O(l)

关于python - 每 k 圈更换计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47907977/

相关文章:

algorithm - 高效的并行握手(组合)

java - 第 N 次组合 ({a, b} = {b, a}) 无重复(枚举/蛮力)

Python - 迭代嵌套列表

python - 如何将字符串拆分为字典并返回特定的字典值?

python - 如何重命名python中的重复字符串?

algorithm - 这个 MergeSort 实现稳定吗?

algorithm - 在 Elm 中将 List (Maybe a) 转换为 Maybe (List a)

algorithm - AVL树删除

python - 如何将不同的模型添加到 ModelForm 作为额外字段?

python - 如何在 Keras/Tensorflow 中返回增强数据