简体   繁体   English

在python中求解(m选择x)= n的高效算法

[英]Efficient algorithm to solve (m choose x) = n in python

Given 特定

m : number of posters to design m :要设计的海报数量
n : total number of available colors n :可用颜色总数

solve for 解决

x : number of colors for each poster so that each poster has a unique combination of colors x :每个海报的颜色数,以便每个海报具有唯一的颜色组合

subject to the equation 服从等式

(n choose x) = m (n选择x)= m

I have coded the above problem in python and the source code is given below 我已经在python中编码了上面的问题,下面给出了源代码

factorial = []

def generateList(n):
    factorial.append(1)
    factorial.append(1)

    for i in range(2,n+1):
        factorial.append(i * factorial[i-1])

def calculateFac(n,i):
    return int((factorial[n]) / (factorial[i] * factorial[n-i]))

def ColorChoice(m,n):
    for i in range(1,int(n/2)+1):
        if m == calculateFac(n,i):
            return i
    return -1

def checkChoose(m,n):
    generateList(n)
    return ColorChoice(m,n)

print (checkChoose(35,7))

The above solution will only work for small integers but I need a solution to work for larger numbers, eg when n = 47129212243960. 上面的解决方案仅适用于小整数,但是我需要一个解决方案来处理较大的数字,例如,当n = 47129212243960时。

Is there any efficient way to solve this? 有什么有效的方法可以解决这个问题吗?

Since (n choose x) == (n choose (nx)) , and it seems like you want to find the minimal x , we can search for x between 0 and n/2 . 由于(n choose x) == (n choose (nx)) ,似乎您想找到最小的x ,我们可以在0n/2之间搜索x Also, for arbitrary n and m , it's possible no such x exists, but probably what you want is the minimal such x , if one exists, such that (n choose x) >= m , ie the smallest x guaranteeing you can make m unique colour combinations -- with that x you may even be able to make more than m unique colour combinations. 另外,对于任意的nm ,可能不存在这样的x ,但可能想要的是最小的x ,如果存在的话,那么(n choose x) >= m ,即保证您可以使m最小的x独特的颜色组合-使用x您甚至可以制作超过m独特的颜色组合。

There's a simple O(n) solution, using the fact that (n choose (x+1)) / (n choose x) == (nx)/(x+1) , which you can see by expanding the "choose" expressions in terms of factorials, and cancelling things out. 有一个简单的O(n)解决方案,使用(n choose (x+1)) / (n choose x) == (nx)/(x+1)的事实,您可以通过展开“选择”来看到用阶乘表示,然后取消。

def x(m,n):
    n_choose_x = 1
    for x in xrange(1, n/2 + 1):
        n_choose_x = n_choose_x * (n+1-x) / x
        if n_choose_x >= m:
            return x
    return -1

print(x(70,8))
print(x(71,8))
print(x(57,8))
print(x(56,8))
print(x(55,8))
print("")
print(x(9999999, 47129212243960))
print(x(99999999471292122439609999999, 47129212243960))
print(x(99999999947129212243960999999471292122439609999999, 47129212243960))

This prints: 打印:

4
-1
4
3
3

1
3
4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM