计数与替换每k转

时间:2017-12-20 14:14:12

标签: python algorithm combinatorics

问题如下:您有n种类型的商品,并且您想要选择l项(订单事项)。只有在您上次选择该项目后选择了k个其他项目时,才能重新取样某个类型的项目。计算您可以形成的项目序列的总数。如果这令人困惑,以下示例将清除:

n = 5l = 6k = 3

答案是5 * 4 * 3 * 2 * 2 * 2。 在第一个回合我们可以选择5个项目中的任何一个。在第二轮,第三轮和第四轮,我们可以选择432剩余项目中的任何一项。然后,在第五个回合中,我们可以再次选择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乘法运算中生成一种解决此问题的算法。

有人可以帮我弄明白我该怎么做吗?

1 个答案:

答案 0 :(得分:1)

似乎你只需要确切数字的剩余部分。答案是:
DownloadFileAsync

您不需要循环来查找(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 squaring。如果O(log(l-k))足够小,则会使整体计算速度明显加快,因为此公式的第一个因子部分是在解决方案的k中计算的。因此,您的实施中的复杂性为O(k)而非O(log(l-k)) + O(k)