所有子集的产品总和,

时间:2016-01-21 11:38:04

标签: algorithm combinatorics number-theory polynomials

我想计算给定$ N $元素集的每个子集的乘积之和。例如,给定集合{1,2,3},答案是1 + 2 + 3 + 1 * 2 + 1 * 3 + 2 * 3 + 1 * 2 * 3.我还想给出模数$ M $

我所知道的是我可以计算$(x - a_1)(x - a_2)...(x - a_n) - 1 $,但这会涉及FFT,因此可能存在一些舍入误差,但是这个想法的主要问题是需要$ O(N \ log ^ 2 N)$时间并且模数$ M $是有问题的。有没有更快的方法来解决这个问题?这不是我的功课,我从老师那里得到了这个任务到练习编程比赛,但我真的遇到了这个问题。

约束:

$ a_i \ le 10 ^ 9 $

$ N \ le 10 ^ 6 $

$ M \ le 10 ^ 9 $

1 个答案:

答案 0 :(得分:5)

有问题的总和是

[(1+a_1)*(1+a_2)*(1+a_3)*...*(1+a_N) - 1] (mod M)

这是

[(1+a_1)%M * (1+a_2)%M * ... * (1+a_N)%M - 1] % M

如果你能做得更好,我会感到惊讶。

这是一个Python实现:

def sumProducts(nums, M):
    p = 1
    for num in nums:
        p = p*((1+num)%M)%M
        if p == 0:
            return M-1
    return (p-1)%M

我上面提到的天真公式的优化是采用每个新因子的产品模数,并在遇到零时使产品短路 - 如果质数因素(计数符合多重性)将会发生这种情况)出现在(1 + a_i)

一个简单的测试:

>>> sumProducts([1,2,3],5)
3

易于手工验证。

压力测试:

>>> from random import randint
>>> nums = [randint(1,1000000) for i in range(100000)]

nums是一百万个随机数,范围为1到100万

当然,

>>> sumProducts(nums,2**32)
4294967295

因为nums中至少有32个奇数(因此a_i为偶数的32个数字1+a_i

另一方面,1000003是一个大于1000000的素数,因此计算不会短路:

>>> sumProducts(nums,1000003)
719694

计算需要一秒钟。