N!含有质因子2的个数

来源:互联网 发布:中国大数据公司排名 编辑:程序博客网 时间:2024/06/05 20:01

       题目来源于《编程之美》上的一道题。第2.2节“不要被阶乘吓到”中提出了一个问题“求N!的二进制表示中最低位1的位置”。这个题目理解起来比较简单,就等价于求N!中质因子2的个数。因为N!中有几个质因子2,就表示N!的二进制表示可以往右移动几位而不丢失最低位的1。而N!中所含的质因子2的个数可以表示为:


所以容易得出如下解法:

解法一:

int lowestOne(int n){        int Ret = 0;        while(n)        {               n>>=1;               Ret += n;         }         return Ret;}

代码来自《编程之美》。

解法二:

N!所含质因子2的个数等于N减去N的二进制表示中1的数目。

下面先来证明这个命题。

设N的二进制表示中1的数目为,则由解法一容易知道。另设恒等函数

示性函数

表示的是当x能够整除2时,其值为0,否则,为1;也即,表示的是x的二进制表示中最后一位数(严格的说是最后一位二进制数,不过在计算时当做十进制数1或0来计算)。

按照递归函数的思想,所有的可计算函数都是可以表示成递归的,下面将恒等函数用递归的形式表示出来。


上面的递归形式并不是最终的,但这种形式有利于我们的推导。注意这里的除法是整除的意思。根据上述递归形式容易得到:



上述表示中的无穷大不用担心,这样写只是为了便于推导。

(2)式的最后一项 ,恰好表示x的二进制表示中1的个数,因为每次除以2就相当于二进

制表示右移一位,然后将最后一位的数当做十进制数来求和。

综上,原命题得证。

而二进制表示的数中1的个数在《编程之美》2.1有给出效率比较高的算法,故可以写出解法二的代码如下。

//用 n&(n-1) 来消掉n的从右往左数的第1个1 int count1(int n){    int sum = 0;    while(n)    {        n &= (n-1);        sum++;    }    return sum;       }//质因子2的个数或最右边一位1的位数int lowestOne(int n){       return n-count1(n);}



2 0
原创粉丝点击