Python性能算法中的不均匀共享

时间:2018-04-25 17:39:32

标签: python python-3.x algorithm performance

一群k男孩应该按照以下方式支付大理石:他们坐成一圈,每个男孩将比他右边的男孩更多地拿一块大理石,然后把剩下的大理石带到袋子里去他左边的男孩。

领导者首先为自己取出1块大理石。他将行李传递给他左边的那个男孩,然后他为自己移走了2个弹珠,并将行李传递到他的左边。然后那个男孩需要3个硬币并将袋子传递到他的左边,依此类推。这个过程一直持续到袋子为空(从袋子里取出的最后一个男孩可能没有那么多的弹珠)。

我想获得LEADER在整个过程中收到的弹珠总数。

这就是我所拥有的,它有效,但它太慢了:

def countMarbles(n, k):
    c = 0
    leader = 0
    while n>0:
        for i in range(k):
            c+=1
            if i == 0:
                if c<=n:
                    leader += c
                else:
                    leader += n
            n -= c
    return leader

1 个答案:

答案 0 :(得分:3)

你正在施放的弹珠是1,然后是2,然后是3 ...... 这种总和有一个公式,1到x的总和是(x)(x + 1) / 2

现在你被给予n,并想知道你可以制作多少次传球。这意味着获得最高x,使(x)(x + 1) / 2低于或等于n。

我们可以通过解决0 = x^2 + x - 2n来解决这个问题。我们可能会得到一个小数结果,所以我们应该取正则答案的最低值。

一旦我们找到了正确的x,我们就会知道包的每一个k通过,1到达领导者。他先获得1个大理石,然后获得k + 1弹珠,然后是2k + 1 ......

如果有x次通过,则x / k的ceil前往领导者。取出始终为1的第一个传球,我们得到k系数大于0的l = ceil(x / k) - 1次传球:((k + 1) + (2k + 1) + ... + (lk + 1)) = (1 + 2 + 3 + ... + l) * k + l = (l * (l + 1) / 2) * k + l.

考虑到领导者从1开始,解决方案是(l * (l + 1) / 2) * k + l + 1

唯一的问题是袋子里剩下的剩余大理石会发生什么。在那些应该成为领导者的情况下,我们还需要考虑它们。为了实现这一点,x必须是k的倍数,这意味着我们完成了这一轮,所以下一个应该是领导者,但是没有足够的弹珠再次通过。

这是一个python实现:

import math

def solve (n, k):
    x = math.floor((-1 + math.sqrt(1 + 8*n)) / 2)
    l = math.ceil(x / k) - 1
    sol = (l * (l + 1) / 2) * k + l + 1
    if x % k == 0 :
        sol += n - (x * (x + 1) / 2)
    return int(sol)