首页 > 代码库 > 关于阶乘的两个问题
关于阶乘的两个问题
关于阶乘的两个问题
这篇介绍两个和阶乘运算相关的两个问题。切记,不可把阶乘的结果计算出来,因为会溢出。也不要转换为字符串来做,因为比较麻烦。一般而言,我们可以通过数学的方法,转化为结果和N有关,而不是N!的结果有关。
1. 计数N!末尾有几个零
给定一个N,计算N!的末端有几个零。这个问题如果把N!计算出来肯定是不现实的。像这种末尾计算有几个零,就是让你算N!的结果是10的多少倍,不是吗。。。类似的让你计算N!的结果的二进制形式最后又几个零,也即使让你计算N!是2的多少倍,这些问题都是相同的。
好了,既然我们知道要知道N!是10的多少倍,因为10不是质数,所以我们不可以直接把1~N都判断一遍,到底有多少数是10的倍数。这是因为假如一个数中有5,一个数有2的倍数,那么它们各自都不能被10除,而它们相乘就可以了~对吧~~所以以后要注意,这样的情况,一定要把10(或者其他的数)转换为质数。
好了,程序在下面,其中有些注意还是比较重要。一定要注意"有些数不只贡献1个,因为它可以被5除多次,所以要有这句".
其中为什么只计算5,而不是判断是否是2的倍数?这是因为自然数中2的倍数的自然数的个数要比5的倍数的自然数的个数多很多。既然要5和2同时出现,那么肯定是计算二者的较小者。比例2的倍数的数有10个,5的倍数的数有两个,那么满足10的倍数的要求一定是5个。
#include<iostream> using namespace std; int count0(int N) { int num = 0; for(int i = 1; i <= N; i++) //因为是阶乘,所以要遍历1~N { int j = i; while(j % 5 == 0) //能够被5除的数都算 { num++; j /= 5; // 有些数不只贡献1个,因为它可以被5除多次,所以要有这句 } } return num; } int main() { cout<<count0(100)<<endl; return 0; }
如果要计算结果的二进制形式有几个零,可以直接用上面的程序,因为2是质数。
2. N!的二进制表示的最低位1的位置
题目的要求是确定N!的二进制表示中最低位1的位置,比如3!=6=0110,那么最低位的二进制就在低位的第二位。
当问题的规律咋看不出来的时候,我们可以先列几个数看看:
1 = 0001:在第1位;
2 = 0010:在第2位;
4 = 0100:在第3位;
8 = 1000:在第4位。
……
初步说明,N/2+1的个数就是答案,假如不能被2整除,那么就是1.
int lowestOne(int N) { int num = 0; while(N) { N >>= 1; num += N; } return num; }
关于阶乘的两个问题