从输入中读取一个数n,求出n!中末尾0的个数。
输入格式:
输入有若干行。第一行上有一个整数m,指明接下来的数字的个数。然后是m行,每一行包含一个确定的正整数n,1<=n<=1000000000。
输出格式:
对输入行中的每一个数据n,输出一行,其内容是n!中末尾0的个数。
输入样例:
3
3
100
1024
输出样例:
0
24
253
代码长度限制
16 KB
时间限制
1000 ms
内存限制
64 MB
解题思路:
首先要明白阶乘函数的递增速度是极快的。从10!开始就有爆炸式的增长。
10!=3 628 800;而11!=39 916 800 ; 12!=479 001 600 13!=6 227 020 800(10位数字)
而int 数据类型的取值范围为-2147483648~2 147 483 647(10位数字)
很明显,从13!开始,具体结果已经不能用int表示了。
所以用int数据类型计算阶乘,最多可以计算到12!。
下面说用long long数据类型计算。
首先要知道long long数据类型的取值范围为
-9223372036854775808~9 223 372 036 854 775 807(19位数字)
20!=2 432 902 008 176 640 000(19位数字)
21!=5.1090942171709e+19 大于long long数据类型的取值范围
很明显从21!开始,具体结果已经不能用long long数据类型表示了。
int 数据类型 long long数据类型分别可以算到的阶乘为十二的阶乘 二十阶乘(十二 二十,刚好便于记忆。)
但是这道题。最大值却是1000000000,明显不是让我们算出阶乘再统计。
再想想,末尾有多少个0,意味着要乘以多少个10,10又等于多少呢?10可以写为2*5。
再所以我们要统计有多少个2*5
很明显我们知道,2为因数的数明显多余5为因数的数,因此我们只要统计有多少个5相乘,因此循环求解就行,我们任意给定一个数,比如说25,里边有5=1*5 10=2*5 15=3*5 20=4*5 25=5*5
可以看出有6个5相乘。
当然我们可以循环统计从最高位逐个递减,看每个数能被5整除几次,加起来即可。但是需要多一层循环。有没有更简单的策略呢?
我们发现,任何数除以五,就相当于它下面有多少个5的倍数,如25/5=5,说明他下面有5个5的倍数5,10,15,20,25。但是25/5=5.。任然是5的倍数,说明可以分为两个5相乘,所以25/(5*5)=1,说明有1个5*5,依此类推,可以算出1个5的,2个5的,3个5的。
代码如下(借鉴于
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>m;
while(m--){
cin>>n;
int t=5,cnt=0;
while(t<=n){
cnt+=n/t; //统计5的个数
t*=5; //一些数可以不止一次除以5
}
cout<<cnt<<endl;
}
return 0;
}