• 《编程之美》2.2 不要被阶乘吓倒


    题目:

    1. 给定一个整数N,nameN的阶乘N!结尾有多少个0呢?

    2.求N!的二进制表示中最低位1的位置

     1 #include <iostream>
     2 
     3 
     4 // 遍历1~N,找到每一个5的倍数包含5这个因数的个数
     5 // 比如 N=34,我们会找到
     6 //      1. 数字5包含1个因数5(5=1*5), 
     7 //      2. 数字10包含1个因数5(10=2*5)
     8 //      3. 数字15包含1个因数5(15=3*5), 
     9 //      4. 数字20包含1个因数5(20=4*5), 
    10 //      5. 数字25包含2个因数5(25=5*5), 
    11 //      5. 数字30包含1个因数5(30=2*3*5), 
    12 //      一共找到1+1+1+1+2+1=7个5
    13 int count0_way1( int N ) 
    14 {
    15     int count = 0; 
    16     for ( int i = 1; i <= N; i++ ) {
    17         int j = i; 
    18         while ( j % 5 == 0 ) {
    19             count++; 
    20             j /= 5; 
    21         }
    22     }
    23     return count; 
    24 }
    25 
    26 // 我们也可以直接在1~N中找到包含因数5的数的个数,
    27 // 比如 N=34的数字中,
    28 //      1. 包含1个因数5的数字有5,10,15,20,25,30,共6个(即34/5的结果)
    29 //      2. 包含2个因数5的数字(即25)有25, 共1个,即34/25的结果,
    30 //      3. 包含3个因数5的数字(即125)有0个,即34/125的结果,
    31 //      4. .....
    32 //      一共找到34/5 + 34/25 = 6+1=7 个
    33 int count0_way2( int N )
    34 {
    35     int count = 0; 
    36     while ( N ) {
    37         count += N / 5; 
    38         N = N / 5; 
    39     }
    40     return count; 
    41 }
    42 
    43 
    44 // 求N!结果中最低位置1的位置,等同于求N!的2的质因数的个数
    45 // 我们可以观察到,
    46 //     1. 任何奇数的二进制表示中,最后一位都是1
    47 //     2. 任意多个奇数相乘的结果依然是奇数,也就是说,奇数相乘,其结果的最后一位1总是在最低位上
    48 //     3. 任意一个数,都可以分解为质因数相乘,在所有的质数中,只有2是偶数,其余的都是奇数
    49 //     4. 一个数乘以2,相当于其二进制表示左移一位, 即最低位的1的位置向左移动一位
    50 //     5. 因此,我们把算式 N! = N*(N-1)*(N-2)*(N-3)....*1 分解质因式,其所有的因子中,只会存在2和奇数(因为质数中只有2是偶数)
    51 //        根据2,奇数的乘积还是奇数,只有因数2才会改变最低位1的位置,每乘一次2(也即出现一个因子2)就会使得1的位置左移一次
    52 //     得到我们的结论:求N!结果中最低位置1的位置,等同于求N!的2的质因数的个数, 
    53 //     求N!中质因数2的个数的方法可以参考Question1的方法2, 
    54 int OnePosition_way1(int N ) 
    55 {
    56     int count = 0; 
    57     while ( N ) {
    58         count += N / 2;
    59         N = N >> 1; 
    60     }
    61     return count + 1; 
    62 }
    63 
    64 
    65 int main( int argc, char** argv )
    66 {
    67     // Question1: 求N!的结果中,结尾0的个数。 
    68     // 求一个乘法算式结果的结尾0的个数,等同于求乘法算式中因子10的个数,而10=2*5,且在自然数的因子中,因子2的个数大于因子5的个数,
    69     // 因此,求这个算式结果的结尾0的个数,等同于求这个算式中因子5的个数
    70     int N = 34; 
    71     std::cout << " count 0 in " << N << std::endl; 
    72     std::cout << " way1: " << count0_way1( N ) << std::endl; 
    73     std::cout << " way2: " << count0_way2( N ) << std::endl; 
    74     std::cout << " DONE " << std::endl; 
    75 
    76 
    77     // Question2: 求N!结果的二进制表示中,最低位1的位置,比如 N=3, N!=3*2*1=6=0b(110), 其结尾最低位1的位置是2.
    78     std::cout << " the positon of lowest 1 : in " << N << std::endl; 
    79     std::cout << " way1: " << OnePosition_way1( N ) << std::endl; 
    80     //std::cout << " way2: " << 1position_way2( N ) << std::endl; 
    81     std::cout << " DONE " << std::endl; 
    82 
    83     return 0; 
    84 }
  • 相关阅读:
    java 基础(Collections 工具类的常用方法)
    Java 基础( Map 实现类: Properties)
    Java 基础(Map)
    Java 基础(集合三)
    Java 基础(集合二)
    Java 基础(集合一)
    Java 基础(Annotation)
    CentOS7 系统 springboot应用启动脚本
    GenericObjectPool源码分析
    问题springboot项目启动报错
  • 原文地址:https://www.cnblogs.com/houjianli/p/16258076.html
Copyright © 2020-2023  润新知