Algorithm to find Sum of the first r binomial coefficients for fixed n modulo m

后端 未结 2 971
天命终不由人
天命终不由人 2021-02-10 17:25

I am trying to find the sum of the first r binomial coefficients for a fixed n.

(nC1 + nC2 + nC3 + ... + nCr) % M

where r < = n.

Is there an efficie

2条回答
  •  抹茶落季
    2021-02-10 17:49

    My first answer was unsatisfactory for several reasons, one of which being that the paper which I referenced is difficult to understand and to implement. So I'm going to propose a different solution to the problem below.

    We want to calculate the sum of the first r binomial coefficients for fixed n, nC0 + nC1 + ... + nC(r-1), modulo M. Instead of reducing the computation of nCk by reducing n, it makes more sense to reduce k: we need nC(k-1) already as part of the sum; in addition, we may have r much less than n, so getting at the values by incrementing n could be far less efficient than incrementing r.

    Here's the idea: First note that if r > n/2 we have nC0 + ... + nC(r-1) = 2^n - (nCr + ... + nCn) = 2^n - (nC0 + ... + nC(n-r)) where n-r < n/2, so we have reduced the problem to the case where r <= n/2.

    Next, apply the identity

    nCk = n!/(k!(n-k)!) = n!/((k-1)!(n-(k-1)!) x (n-k+1)/k = nC(k-1) x (n-k+1)/k
    

    to calculate the terms of the sum in order. If out integers were unbounded in size, we could calculate

    sum = 0;
    nCi = 1; // i=0
    for i = 1 to r-1
      sum += nCi;
      nCi *= (n-k+1);
      nCi /= k;
    sum %= M;
    

    The problem with this is that numbers nCi (and therefore sum) can become enormous, so we have to use big integers, which slow down the calculation. However, we only need the result mod M, so we can use ints if we perform calculations mod M inside the loop.

    Sum and product are straightforward mod M, but division isn't. To divide nCi by k mod 10^6, we need to write nCi and k in the form 2^s 5^t u where u is relatively prime to 10^6. Then we subtract exponents, and multiply by the inverse of u mod 10^6. In order to write nCi in that form, we also need to write n-k+1 in that form.

    To put k and n-k+1 into the form 2^s 5^t u where u is relatively prime to 10^6, we could repeatedly check for divisibility by then divide by 2, and the same for 5. However, it seems there should be a faster way.

    In any case, the algorithm is now O(r), which seems to be the fastest possible, barring the discovery for a simple mathematical expression for the sum.

提交回复
热议问题