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

不要被阶乘吓到

时间:2015-09-22 01:28:45      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:阶乘0的个数   阶乘1的排位   阶乘计算技巧   

编程之美有一道关于阶乘的题目:
1给定一个整数N,那么N的阶乘等于N!,末尾有多少个0呢,例如N=10,N!=3628800,N!的末尾有两个0
2求N!的二进制表示中最低位为1的位置。
阶乘定义:

n!={1n(n?1)!n=0n>0?nN

作者对于问题一的分析:对N!进行质因数分解: N!=2X*3Y*5Z…,因为10=2*5,所以M与2和5的个数即X、Z有关。每一对2和5都可以得到10,故M=min(X,Z)。因为能被2整除的数出现的频率要比能被5整除的数出现的频率高,所以M=Z。
解法一:
直接计算因式分解中5的指数,然后求和.
代码实现:

#include <iostream>
using namespace std;
int findZero(int N)
{
   int ret=0;
   for(int i=1;i<=N;i++)
   {
      int j=i;
      //计算每个阶乘相乘数字分解因式5的个数
      while(j%5==0)
      {
         ret++;
         j/=5;
      }
   }
   return ret;
}

解法二:
作者根据[N/k]等于1,2,3 ,…,N中能被k整除的数的个数规律,得出下面公式:
Z=[N/5]+[N/52]+[N/53]+….(总存在一个K,使得5k>N,[N/5k]=0)
公式中,[N/5]表示不大于N的数中5的倍数贡献一个5,[N/52]表示不大于N的数中52的倍数再贡献一个5…。
代码实现:

#include <iostream>
using namespace std;
int findZero(int N)
{
   int ret=0;
   while(N)
   {
      //计算1,2,3...k能被当前5的指数倍数整除个数
      ret+=N/5;
      //累计5的指数
      N/=5;
   }
   return ret;
}

对于问题二,确实不好想到那方面去,我们都知道在计算机二进制里,有一个规律,那就是如果一个数是偶数,那么该数的最后一个二进制必定是0,如果是奇数,那么该数的最后一个二进制必定是1,这里作者根据这样的规律给了两种解法。
解法一:
判断最后一个二进制位是否为0,若为0,则将此二进制数右移一位,即为商值;反之,若为1,则说明这个二进制数是奇数,无法被2整除。
所以,这个问题实际上等同于求N!含有质因数2的个数。即答案等于N!含有质因数2的个数加1。
代码实现:

#include <iostream>
using namespace std;
int lowestOne(int N)
{
   int ret=0;
   //统计被2整除的个数
   while(N)
   {
      N>>=1;
      ret+=N;
   }
   return ++ret;
}

解法二:
N!含有质因数2的个数,还等于N减去N的二进制表示中1的数目。我们还可以通过这个规律来求解。
下面对这个规律进行举例说明,假设 N = 11011,那么N!中含有质因数2的个数为 N/2 + N/4 + N/8 + N/16 + …
即: 1101 + 110 + 11 + 1
=(1000 + 100 + 1)
+(100 + 10)
+(10 + 1)
+ 1
=(1000 + 100+ 10 + 1)+(100 + 10 + 1)+ 1
= 1111 + 111 + 1
=(10000 -1)+(1000 - 1)+(10-1)+(1-1)
= 11011-N二进制表示中1的个数
代码实现:

#include <iostream>
using namespace std;
int lowestOne(int N)
{
   int ret=0;
   int temp=N;
   //统计被2整除的个数
   while(temp)
   {
      ret+=temp&1;
      temp>>=1;
   }
   ret=N-ret;
   return ++ret;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

不要被阶乘吓到

标签:阶乘0的个数   阶乘1的排位   阶乘计算技巧   

原文地址:http://blog.csdn.net/xuguoli_beyondboy/article/details/48634239

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