zoukankan      html  css  js  c++  java
  • 阶乘相关问题

     定义:
          一个正整数的阶乘(英语:factorial)是所有小于及等于该数的正整数的积,并且有0的阶乘为1。自然数n的阶乘写作n!。
        亦即n!=1×2×3×...×n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。
     
    问题1、给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N = 10 , N! = 3628800,N!的末尾有两个0。
     
    解析:加入完整得计算N!的阶乘,很可能发生溢出。我们可以从另外的角度出发,“哪些数相乘能的到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,因为能被2整除的书出现的频率比被5整除的数高得多,所以吧公式化简为M = Z(能整除的5的个数);
     
    方法1:
        最直接的方法,计算i(1,2,3,……,N)的因式分解中5的指数,然后求和。
    /**
      * 计算N的阶乘结果末尾0的位数
      * @param N 求阶乘的数
      * @return N的阶乘结果末尾0的位数
      */
     public static int getLowZeroNum(int N)
     {
      int ret = 0;
      int j ;
      for(int i = 1 ; i <=N ; i++)
      {
       j = i;
       while(j % 5 == 0)
       {
        ret ++;
        j = j / 5;
       }
      }
      return ret;
     }
    方法2:公式法
            公式:Z = 【N/5】 + 【N/5的平方】 + 【N/5的立方】+……, (不用担心这回事一个无穷的运算,因为总存在一个K,使得 5的K次方 > N,【N/5的K次方】 = 0。
            公式中,【N/5】表示不大于N的数中5的倍数贡献一个5,【N/5的平方】表示不大于N的数中,5的平凡的倍数在贡献一个5…… 代码如下:
    /**
      * 计算N的阶乘结果末尾0的位数
      * @param N 求阶乘的数
      * @return N的阶乘结果末尾0的位数
      */
     public static int getLowZeroNum2(int N)
     {
      int ret = 0;
      while(0 != N)
      {
       ret += N/5;
       N /= 5;
      }
      return ret;
     }


     
    问题2、求N!的二进制表示中最低位1的位置
            把一个2进制数除以2,判断最后一个二进制位是否为0;若为0,则将此二进制数右移一位,即为商值;反之,若为1,则说明这个二进制数是奇数,无法被2整除。所以这个问题实际上等同于求N!含有质因数2的个数。即答案等于N!含有质因数2的个数加1
     
    解法1:
            N!中含有质因数2的个数,等于【N/2】+【N/4】+【N/8】+【N/16】+ ……,
    具体算法如下:
    /**
      * N的阶乘最低位1的位置
      * @param N 求阶乘的数
      * @return N的阶乘最低位1的位置
      */
     public static int getThePosition(int N)
     {
      int ret = 0;
      while(0 != N)
      {
       N = N >> 1; //右移一位,相当于十进制除以2
     
       ret += N; //不大于当前N的2的倍数的个数
      }
      return ret;
     }

     
    测试:
    public static void main(String[] args)
     {
      //测试计算N的阶乘结果末尾0的位数
      int N = 5;
      System.out.println(N + "的阶乘结果末尾0的位数:" + Factorial.getLowZeroNum(N));
      System.out.println(N + "的阶乘结果末尾0的位数:" + Factorial.getLowZeroNum2(N));
     
      //测试N的阶乘最低位1的位置
      System.out.println(N + "N的阶乘最低位1的位置:" + Factorial.getThePosition(N));
     }
    结果:
    5的阶乘结果末尾0的位数:1
    5的阶乘结果末尾0的位数:1
    5N的阶乘最低位1的位置:3
     
    小结:
        任意一个长度为m的二进制数N可以表示为 N = b[1] + b[2]*2 + b[3]*4 + …… + b[m]*2的m-1次方 ,其中b[i]表示此二进制数第i位上的数字(1或0)。所以,若最低位b[1]为1,则说明N为奇数;反之为偶数,将其除以2,即等于将整个二进制数向低位移一位。 
     
     
     
     
     
     
  • 相关阅读:
    JedisConnectionException: java.net.ConnectException: Connection refused
    Mysql索引整理总结
    jstat命令总结
    Java死锁排查和Java CPU 100% 排查的步骤整理
    Spring-Session实现Session共享实现原理以及源码解析
    Spring-Session实现Session共享Redis集群方式配置教程
    Spring-Session实现Session共享入门教程
    Redis高可用集群-哨兵模式(Redis-Sentinel)搭建配置教程【Windows环境】
    jsp获取当前日期,包括星期几
    使用joda-time工具类 计算时间相差多少 天,小时,分钟,秒
  • 原文地址:https://www.cnblogs.com/0201zcr/p/4637492.html
Copyright © 2011-2022 走看看