设计一个算法,计算出n阶乘中尾部零的个数 样例 11! = 39916800,因此应该返回 2 挑战 O(logN)的时间复杂度
要判断末尾有几个0就是判断可以整除几次10。10的因子有5和2,而在0~9之间5的倍数只有一个,2的倍数相对较多,所以本题也就转换成了求N阶乘中有几个5的倍数。比如10的阶乘,10之内有2个5的倍数,10/5=2,2之内则没有了可以匹配的5了,所以一共2个5。
还有25阶乘中贡献了6(25/5+5/5)个5,因为有5的倍数的倍数(25=5*5,贡献2个5),所以就有了count += n/5,在先求一批5的个数后,再求第二批5的个数。
同理 125中 5的个数等于125/5 + 25/5 +5/5=31;
#include<iostream> using namespace std; int main() { int n; cin>>n; int count = 0; while(n) { n /= 5; //算出当前数字中可以匹配5(5和5的倍数)的个数 count += n; //累加之 } cout<<count; return 0; }
n的阶乘尾部有q个连续的0,现在给你q,请你算出满足条件的n,如果有多个n满足条件,输出最小的那个即可。
Input
输入一个T(T <= 10000),表示样例数量。
每个样例输入一个q。(1 <= q <= 100,000,000)
Output
对于每个样例,输出满足条件的最小的n,如果没有满足条件的则输出"impossible"。.
Sample Input
3
1
2
5
Sample Output
Case 1: 5
Case 2: 10
Case 3: impossible
解析:因为阶乘中0的个数是按照数的增大而递增的(满足单调性)
#include<iostream> #include<algorithm> using namespace std; //因为0的个数是随这数的增加而增加的 int judge(int x){ int ans=0; while(x){ ans+=x/5; x/=5; } return ans; } int main(){ int t,n; cin>>t; int kase=0; while(t--){ cin>>n; int l=0,r=1e9; int ans=0; while(l<=r){ int mid=(l+r)/2; int p=judge(mid); if(p>=n){ r=mid-1; ans=mid; } else{ l=mid+1; } } ans=(ans-ans%5);//因为是最小的那个 if(judge(ans)==n) printf("Case %d: %d ",++kase,ans); else{ printf("Case %d: impossible ",++kase); } } }