不要被N!吓到--《编程之美》例题

 

/*
不要被阶乘吓到!
来着《编程之美》例题。
问题:
1、给定一个整数N,求N!的末尾0的个数。
2、求N!的二进制表示中最低位1的位置。
*/
#include <stdio.h>
#include <stdlib.h>

/*
在做之前,应该理解一个规律:
[N/k]等于1,2,3、、、,N中能被k整除的数的个数。
在下面计算5的质因子个数时会有讲解。
*/

//第一个问题:
//求末尾0的个数,其实就是求这个N!能有多少个乘数为10。
//如果按照传统的方法,先计算出N!的结果再来看有多少个0,那就很不实际,结果很容易越界。
//再进一步,我们只是求N!中,10作为乘数的个数。10=2*5;
//也就是说只要求2*5的个数就行;
//进行质因数分解:N! = (2^x) * (3^y) * (5^z) 、、、
//2*5的个数= min(x, z)。再进一步考虑,发现,能被2整除的数的频率高于被5整除的数。即2*5 的个数 = min(x, z) = z;
//现在我们来利用上面提到的那个规律:z = [N/5] + [N/5^2] + [N/5^3] +、、、
//怎么理解? 我们可以这么想,当求N!时,我们要求小于N中5的倍数,
//如N= 32; 则5的倍数有5,10,15,20,25,30。在这6个数中有多少个5呢,为1+1+1+1+2+1 = 7。即N!末尾有7个0.
//函数实现如下:
int Count0(int N)
{
 int res(0);
 while(N)
 {
  res += N / 5;
  N /= 5;
 }
 return res;
}

//第二题:求N!二进制表示中末尾最后一个1的位置。
//我们可以改变一下问法:求N!二进制中末尾有多少个0?是不是跟上题很像。
//或者将上题换个说法,求N!十进制表示中第一个不为0的数的位置。
//嗯,其实这两题是很相似的,只是一个是2进制表示,一个是十进制表示。
//解题的思路也差不多:
int CountLastOne(int N)
{
 int res(0);
 while(N)
 {
  N >>= 1;
  res += N;
 }
 return res;
}

int main()
{
 int N;
 scanf(“%d”, &N);
 printf(“%d\n”, Count0(N));
 printf(“%d\n”, CountLastOne(N));

    system(“pause”);
 return 0;
}

 

注:在资源中上传了源码文件

    原文作者:wche1990
    原文地址: https://blog.csdn.net/wche1990/article/details/6942589
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞