码迷,mamicode.com
首页 > 其他好文 > 详细

不要被阶乘吓倒

时间:2016-07-10 18:34:16      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:

题目1:给定一个整数N,那么N的阶乘N!末尾有几个0呢?
例如:N=10,N!=3628800;N!的末尾有两个0。

方案一:我们一般都会想到就算出完成的N!的阶乘的结果,再看有几个0。但是这样会涉及到值的溢出!
方案二:我们可以考虑不用完全计算出阶乘的结果,这样可以避免方案一中的溢出情况,也会使问题变得简单。我们可以从“哪些数相乘能得到10”的这个角度来考虑,问题就变的简单了!首先考虑,如果N=K*10^m,且K不能被10整除,那么N!末尾有m个0.再考虑对N!进行质因数分解,N!=2^x*3^y*5^z...由于10=2*5,所以m只跟x和z有关,每一对2*5都可以得到一个10,于是m=Min(X,Z),不难看出X大于等于Z,所以我们只需要考虑Z的个数就行了。
方案一解法如下:要计算Z,最直接的方法,就是计算i(i=1,2...,n)的因式分解中5的指数,(1*2*3*4....*n),然后求和:
ret=0;
for(i=1;i<=N;i++)
{
   j=i;
   while(j % 5==0)
   {
      ret++;
      j/=5;
   }
}
由上可看出,循环中有许多不要的步骤,因为只需要求5的指数个数即可,上述还可以改进如下:
ret=0;
for(i=1;i<=N;i*=5)
{
   j=i;
   while(j % 5==0)
   {
      ret++;
      j/=5;
   }
}
方案二解法如下;Z=[N/5]+[N/5^2]+[N/5^3]+....(公式中[N/5]表示不大于N的数中5的倍数贡献一个)。
例如:N = 25 ,即1~25,5的倍数(5,10,15,20,25)贡献一个5,25的倍数贡献一个5,虽然25可以贡献两个5,但是已经在5的倍数中贡献一次了,所以这里就统计一次。也就是说,对于每一个5 ^M,N只统计一次5,虽然它本身有多个5的质因数,但是已经在前面M-1计算过,所以只需统计一次即可。
具体实现代码:
ret=0;
while(N)
{
  ret+=N/5;
  N/=5;
}
题目2:求N!的二进制中最低位1的位置。
例如N=3;N!=6.其二进制为0110.其二进制中1的最低位置为2。

方案一:这里我们可以通过统计质因数2的个数来求解:和上面的思路一样,N/2+N/4+N/8+N/16+..
具体实现代码:
int lowestOne(int N)
{
   int Ret=0;
   while(N)
   {
      N>>1;
      Ret+=N;
   }
   return Ret+1;
}
方案二:这里我们还可以根据N减去N的二进制中1的数目这个规律来求解。
其具体实现代码如下:
int count(int n)//统计1的个数;
{
	int Ret=0;
	while( n )
	{
		Ret++;
		n= n&(n-1);
	}
	return Ret;
}
int FindLowestOne(int num)//num中最低位1的位置;
{
	return num-count(num)+1;
}
相关题目;给定整数n,判断它是否为2的方幂。
实现:
if(n & (n-1))==0)


不要被阶乘吓倒

标签:

原文地址:http://blog.csdn.net/gogokongyin/article/details/51871692

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!