题目:

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=2*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 }
05-11 15:22