Question:
对任意输入的正整数N,编写C程序求N!的尾部连续0的个数,并指出计算复杂度。如:18!=6402373705728000,尾部连续0的个数是3。(不用考虑数值超出计算机整数界限的问题)
Answer:
There is a formula for finding the number of zeros a factorial number will have.
It is:
floor(n/5) + floor(n/25) + floor(n/125) + ... + floor(n/5^n) + ...
The floor function means round down to the nearest integer.
For example, let's take 5!, or n = 5.
floor(5/5) = floor(1) = 1.
So, 5! ends in 1 zero.
Let's go to 15!
floor(15/5) = floor(3) = 3
So, 15! ends in 3 zeros.
Let's move on to 100!.
floor(100/5) + floor(100/25) = floor(20) + floor(4) = 20 + 4 = 24
If you went to 200, you would have to use the next power of 5, or 5^3 = 125.
The reason this works is that a number ends in 0 if it is divisible by 10. Divisible by 10 means divisible by both 5 and 2. But there are lots of numbers divisible by 2 (half of them). So, we concentrate on the number of times a number is divisible by 5. But there are tricky numbers like 25, which are divisible by 5 twice, so we have to take those into account (or floor(n/25)). Then again, there are numbers that are divisible by 5 three times, like 125, so we have to take them into account.
Program:
[1] no consider about cross-border.
#include <iostream> using namespace std; int fac(int n) { for (int i=n,res=1; n!=0; n--) { res*=n; } return res;//3628800 } int main() { //计算10!的末尾连续0的个数 int n=10; int count=0; int total=fac(n); int res=0; while (1) { res=total%10; if (res==0) { count++; total/=10; } else { break; } } cout<<"count= "<<count<<endl;//2 return 0; }
[2] if N! is so big that any variable can not take it.
#include <iostream> #include <math.h> using namespace std; int main() { //计算1000!的末尾连续0的个数 int n=1000; int count=0; for (int i=1; pow(5,i)<n; i++) { n/=pow(5,i); count+=n; n=1000; } cout<<"count= "<<count<<endl;//249 return 0; }
[3] a simple way to count.
#include <iostream> using namespace std; int main() { // 计算25!的末尾连续0的个数 int n=25; int count=0; while (n>=5) { n/=5; count+=n; } cout<<"count= "<<count<<endl;// 6 return 0; }
[4] a recursive way to count.
#include <iostream> using namespace std; int zero(int i)//不会产生溢出 { if(i < 5) { return 0; } return (i/5) + zero(i/5); } int main() { //计算1000!的末尾连续0的个数 int n=1000; int count=zero(n); cout<<"count= "<<count<<endl;//249 return 0; }