Math 人物-苹果拼图[受客户端拼图协议启发]

Math 人物-苹果拼图[受客户端拼图协议启发],math,probability,puzzle,Math,Probability,Puzzle,我正在学习一个客户端谜题协议,我有一个关于寻找解决方案可能性的问题。以下是一个场景,而不是直接讨论协议事实: 假设我有x个人,我有y个苹果: 每个人必须至少有一个苹果 每个人最多只能吃z个苹果 是否有计算方案数量的公式 例如: 4个人[x],6个苹果[y],最多15个苹果[z] 手工计算的情景数量:10 如果我的数字很大,我希望用公式来计算 感谢您的帮助。您的问题相当于“通过将z数字相加,找到可以获得x的方法的数量,每个数字位于min和max之间”Python实现示例: def possib

我正在学习一个客户端谜题协议,我有一个关于寻找解决方案可能性的问题。以下是一个场景,而不是直接讨论协议事实:

假设我有x个人,我有y个苹果:

  • 每个人必须至少有一个苹果
  • 每个人最多只能吃z个苹果
是否有计算方案数量的公式

例如: 4个人[x],6个苹果[y],最多15个苹果[z]

手工计算的情景数量:10

如果我的数字很大,我希望用公式来计算


感谢您的帮助。

您的问题相当于“通过将
z
数字相加,找到可以获得
x
的方法的数量,每个数字位于
min
max
之间”Python实现示例:

def possible_sums(x, z, min, max):
    if min*z > x or max*z < x:
        return 0
    if z == 1:
        if x >= min and x <= max:
            return 1
        else:
            return 0
    total = 0
    #iterate from min, up to and including max
    for i in range(min, max+1):
        total += possible_sums(x-i, z-1, min, max)
    return total

print possible_sums(6, 4, 1, 15)
当调用大量函数时,此函数可能会变得非常昂贵,但可以通过使用来改进运行时。如何实现这一点取决于语言,但传统的Python方法是将先前计算的值存储在字典中

def memoize(fn):
    results = {}
    def f(*args):
        if args not in results:
            results[args] = fn(*args)
        return results[args]
    return f


@memoize
def possible_sums(x, z, min, max):
    #rest of code goes here

现在
打印可能的总和(60,40,1150)
,这将花费很长的时间来计算,会在瞬间返回
2794563003870330

有数学方法可以做到这一点。这类似于询问在3个6面骰子(x=3,y=10,z=6)上总共掷10个骰子的方法有多少。您可以通过几种不同的方式实现这一点

一种方法是使用包含排除。将y写为x正数之和(无最大值)的方法数为y-1。通过选择x-1。您可以计算将y写入x正数之和的方法数,这样,如果y-x-sz为负数,则其中的一组方法至少为z+1:0,如果y-x-sz为非负数,则y-1-sz选择x-1。然后,您可以使用将计数写入s的非负值之和,以便y-x-sz是(-1)^s(x选择s)(y-1-sz选择x-1)的非负值

可以使用生成函数。你可以让某个变量的幂,比如说t,保持总数,系数表示有多少个组合与这个总数。那么你要求的是(t+t^2+…+t^z)^x中t^y的系数。你可以用几种方法来计算

一种方法是使用动态规划,计算k到x的(t+t^2+…+t^z)^k系数。这种简单的方法可能已经足够快了:你可以计算k=1,2,3,…,x。使用类似重复平方运算的方法要快一点,例如,为了计算87次方,可以将87以二进制形式展开为64+16+4+2+1=0b1010111(以二进制文字形式编写)。您可以通过平方和乘法来计算1、2、4、16和64次幂,也可以通过计算0b1、0b10、0b101、0b1010、0b10101、0b101011和0b1010111次幂来节省一些空间

另一种方法是使用二项式定理两次

(t+t^2+...+t^z)^x = t^x ((t^z-1)/(t-1))^x 
                  = t^x (t^z-1)^x (t-1)^-x. 
指数为x的二项式定理允许我们将(t^z-1)^x重写为(-1)^s t^(z(x-s))(x选择s)的和,其中s的范围为0到x。它还允许我们将(t-1)^-x重写为(r+x-1选择x-1)t^r与非负r的无穷和。然后我们可以挑选出有助于t^y(r=y-x-sz)系数的有限项集,我们得到与上述包含排除相同的和

例如,假设x=1000,y=1100,z=30。价值是


=1.29 x 10^144。

作为一个起点:向x个至少需要Q个苹果的人分发Y个苹果的可能性与向x个需要0个苹果的人分发(Y-Q*x)个苹果的可能性相同。4个人,6个苹果,1个需要与4个人,2个苹果,0个需要相同。谢谢你的回答。。我理解那一部分。。但是,我还需要考虑场景中的MAX Apple部分
(t+t^2+...+t^z)^x = t^x ((t^z-1)/(t-1))^x 
                  = t^x (t^z-1)^x (t-1)^-x.