以二进制计算二项式系数

Posted

技术标签:

【中文标题】以二进制计算二项式系数【英文标题】:Calculate binomial coefficient in binary 【发布时间】:2021-12-27 02:28:03 【问题描述】:

是否有一种快速算法来计算二项式系数并将结果保留为二进制。例如,(10 选择 8) = 101101。我不需要将结果转换为以 10 为底,而是希望将结果存储为二进制字符串。在重新发明***之前,我一直在问这个问题。

【问题讨论】:

您当然意识到,对于普通整数计算,内部表示已经是二进制的。只有当您使用printf("%d") 之类的东西时,整数才会转换为十进制。 话虽如此,种直接计算C(n,k)的方法不涉及显式计算n! k! ,因此不会很快溢出。 (如果这就是你所担心的。) 哦!好的。对不起,如果我侮辱了你的智商。 (我们总是在这里收到提问者对整数运算内部如何工作的最异想天开的想法。)不过,我怀疑二进制中是否存在捷径。大多数数学算法(包括我所知道的组合数学算法)只处理数字,而不关心它们的基数。所以你可以用+*!来写它们,或者my_binary_addmy_binary_multmy_binary_factorial,最后一切都会一样。 那恐怕你没有比乘除法更好的选择了。 您的目标是处理大数字,还是非常具体地处理单个 0 和 1?一方面,您肯定需要一些特殊的代码来处理大数字,因为(1000 选择 500)是一个 300 位、995 位的数字。但是为了提高效率,大多数 bignum 代码都在“块”上工作,而不是一次一点。 (例如,我刚刚测试这个例子的 bignum 代码将 (1000 C 500) 表示为 33 个“字”,每个 31 位。)没有理由不能将此数字表示为具有 995 个单独位的数据结构,并且这可能很有趣,但不太实用。 【参考方案1】:

我找到了最有效的方法。它正在执行二项式系数的素数分解,然后转换为二进制。我添加了非常快速的代码来查找二项式系数的素数分解。它称为Kummer's theorem,您可以使用此online calculator 来验证您的结果。分解算法来自这个Jstor paper。这是一个Haskell 版本,如果你喜欢那种东西的话。请注意,您需要首先自己生成一个素数列表。然后测试单个素数。此外,算术基本定理也在起作用。

//Note primeNumber is always less than n
//Inputs n,k,primeNumber 
//Output: e (the exponent of prime number)
//Note: 0 means primeNumber is not a factor of this binomial coefficient
//Example: (n=10,k=3,primeNumber=3), e = 1
//So if you had a list of primes 2,3,5 then for each you get e=3,e=1,e=1. (10,3) = 2^3 *3^1 * 5 ^1 
int BinomialFactorization(int n, int k, int primeNumber)

    int a = 0;
    int b = 0;
    int exponent = 0;
    int r = 0;
    
    //Finds smaller value between n and n-k since (n choose k) == (n choose n-k)
    //Algorithm only works when k < n/2 
    if(k > (n/2))
       
        k = n - k; 
    
    //Speeds up according to paper
    if(primeNumber > n - k)
    
        return 1;
    
    //Speeds up according to paper
    if(primeNumber > n/2)
    
        printf("%d", 0);
        return 0;
    
    if(primeNumber * primeNumber > n)
    
        if(n % primeNumber < k % primeNumber)
           
            return 1;
        
        else
           //Saw this on online calculator
            return 0;
        
    
    //Changing base algorithm 
    while(n > 0)
    
        a = n % primeNumber;
        n = n / primeNumber;
        b = k % primeNumber + r;
        k = k / primeNumber;
        if(a < b)
        
            exponent = exponent + 1;
            r = 1;
        
        else
        
            r = 0;
        
    
    return exponent;    

【讨论】:

以上是关于以二进制计算二项式系数的主要内容,如果未能解决你的问题,请参考以下文章

UVa 10883 超级平均数(二项式系数+对数计算)

二项式系数和公式

使用动态规划计算二项式系数

计算具有大二项式系数的总和

动态规划_二项式系数

如何使用 memoization 计算二项式系数?