具有相同数量的0和1的二进制数

时间:2010-08-19 13:49:24

标签: algorithm math

当我解决Euler project problem #15时,我意识到它可以通过从开始到结束的路线组合方式来解决。生成的路径始终具有相同大小的向右或向下选择(或0和1),而正确的路径始终具有相同的0和1的数量。 因此,二进制字中具有相同数量0和1的数字的数量是 C(2,1)为1位长度 C(4,2)为2位“” C(6,3)为4位“” ...

现在我的问题出现了: 如果一个数字具有相同的0和1的数量,是否有一个函数可以解决? 我想它更像是一个逻辑函数,我不想迭代所有数字或使用正则表达式(这将比迭代更糟)。

**其他问题是关于这种“平衡”价值观之间的增长和空间吗?

6 个答案:

答案 0 :(得分:5)

您正在寻找 popcount 函数,该函数计算给定数字中的设置位数。有些处理器内置了,有些则没有。

c=0; while (n &= (n-1)) c++;

完成工作,但会摧毁n

有关更好的算法,请参阅this link,或google“popcount”。

答案 1 :(得分:3)

作为Paul R答案的后续内容, 简化了中心二项式系数的公式,请参阅http://mathworld.wolfram.com/CentralBinomialCoefficient.html

p = n! /((n / 2)!)²= 2 n / 2 (n-1)!! /(n / 2)!

ķ!!是“双因子”,这意味着你在计算时跳过所有其他数字:k !! = k *(k-2)*(k-4)* ...(只要因子为正)。

对于你的计算,很多数字都会被取消(你可以在计算分子和分母时同时使用gcd)

答案 2 :(得分:1)

如果我理解正确,那么p = nCr r = n/2 p = n! / ((n/2)! * (n/2)!)。所以:

{{1}}

答案 3 :(得分:0)

可以通过想象你在路上选择路径来直接找到平衡值(即选择从n开始2n次。)

因此,这些值C(2n,n)2n! / (n! * n!)。值的总数当然是2^2n。使用斯特林的近似值,我们找到了

ln n! ~= n ln n - n + ln(2*pi*n)/2
ln 2n!/(n!*n!) = ln(2n!) - 2*ln(n!) ~= 2n*ln(2) - n + ln(4*pi*n)/2 - ln(2*pi*n)

这样好的值的分数C(2n,n)/2^(2n)

exp(2n*ln(2) - n + ln(4*pi*n)/2 - ln(2*pi*n) - 2n*ln(2)) =
exp(-n)/sqrt(pi*n)

因此,良好值的数量呈指数下降。

这就是为什么直接选择它们而不是测试它是明智的。

但如果你真的想测试,有各种比特计数方法here。 (Kernighan可能是最快的 - 但是他不是第一个注意到它的人,并且已经在这里发布了一个等效的算法!)

答案 4 :(得分:0)

您可以使用查找表将n-bt数字映射到其1-count。例如,如果您总是使用23位无符号整数,则16位和7位的查找表将允许您拆分数字,并从查找表中为16位和7位部分添加一位数。 (7位查找表可能只是16位表的一部分)。

答案 5 :(得分:0)

对于'i'的偶数值,2 ^ i和2 ^(i-1)之间的这些数字(等于1和0)的数量由以下公式给出:

(I-1)!/ [X! *(x-1)!]

其中x = i / 2。

我尝试在C中编写一个程序来生成它,但它溢出了。然后我用浮点运算做到了。直到我= 56它的好处。之后,准确度会下降。

但BigInt库应该能够完成这项任务而不会溢出。