Fastest way to generate binomial coefficients

后端 未结 11 1762
[愿得一人]
[愿得一人] 2020-12-13 02:20

I need to calculate combinations for a number.

What is the fastest way to calculate nCp where n>>p?

I need a fast way to generate binomial coefficients for a

11条回答
  •  庸人自扰
    2020-12-13 03:02

    I recently wrote a piece of code that needed to call for a binary coefficient about 10 million times. So I did a combination lookup-table/calculation approach that's still not too wasteful of memory. You might find it useful (and my code is in the public domain). The code is at

    http://www.etceterology.com/fast-binomial-coefficients

    It's been suggested that I inline the code here. A big honking lookup table seems like a waste, so here's the final function, and a Python script that generates the table:

    extern long long bctable[]; /* See below */
    
    long long binomial(int n, int k) {
        int i;
        long long b;
        assert(n >= 0 && k >= 0);
    
        if (0 == k || n == k) return 1LL;
        if (k > n) return 0LL;
    
        if (k > (n - k)) k = n - k;
        if (1 == k) return (long long)n;
    
        if (n <= 54 && k <= 54) {
            return bctable[(((n - 3) * (n - 3)) >> 2) + (k - 2)];
        }
        /* Last resort: actually calculate */
        b = 1LL;
        for (i = 1; i <= k; ++i) {
            b *= (n - (k - i));
            if (b < 0) return -1LL; /* Overflow */
            b /= i;
        }
        return b;
    }
    

    #!/usr/bin/env python3
    
    import sys
    
    class App(object):
        def __init__(self, max):
            self.table = [[0 for k in range(max + 1)] for n in range(max + 1)]
            self.max = max
    
        def build(self):
            for n in range(self.max + 1):
                for k in range(self.max + 1):
                    if k == 0:      b = 1
                    elif  k > n:    b = 0
                    elif k == n:    b = 1
                    elif k == 1:    b = n
                    elif k > n-k:   b = self.table[n][n-k]
                    else:
                        b = self.table[n-1][k] + self.table[n-1][k-1]
                    self.table[n][k] = b
    
        def output(self, val):
            if val > 2**63: val = -1
            text = " {0}LL,".format(val)
    
            if self.column + len(text) > 76:
                print("\n   ", end = "")
                self.column = 3
            print(text, end = "")
            self.column += len(text)
    
        def dump(self):
            count = 0
            print("long long bctable[] = {", end="");
    
            self.column = 999
            for n in range(self.max + 1):
                for k in range(self.max + 1):
                    if n < 4 or k < 2 or k > n-k:
                        continue
                    self.output(self.table[n][k])
                    count += 1
            print("\n}}; /* {0} Entries */".format(count));
    
        def run(self):
            self.build()
            self.dump()
            return 0
    
    def main(args):
        return App(54).run()
    
    if __name__ == "__main__":
        sys.exit(main(sys.argv))
    

提交回复
热议问题