Description
從輸入中讀取一個數n,求出n!中末尾0的個數。
Input
輸入有若干行。第一行上有一個整數m,指明接下來的數字的個數。然後是m行,每一行包含一個確定的正整數n,1<=n<=1000000000。
Output
對輸入行中的每一個數據n,輸出一行,其內容是n!中末尾0的個數。
Sample Input
3
3
100
1024
Sample Output
0
24
253
思路
10 = 2*5,求出1-n這些數中能夠分解出多少個2和多少個5,則選取較小的那個數便是階乘末尾0的個數。
很顯然,能分解出5的個數肯定比2少,那麼代碼如下:
用ans記錄能夠分解出5的個數,i從5開始遍歷,每次遞增5,到n結束。
第一次提交
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<inttypes.h>
using namespace std;
int64_t sumzero(int64_t n)
{
if(n <= 4) return 0;
int ans,ans1=0,ans2=0;
for(int64_t i=5;i<=n;i=i+5){
int64_t j = i;
while(j%5==0) {ans2++;j /= 5;}
}
return ans2;
}
int main()
{
int64_t n,m;
while(cin>>n){
for(int i=1;i<=n;i++){
cin>>m;
cout<<sumzero(m)<<endl;
}
}
return 0;
}
1<=n<=1000000000
但是n太大了,運行超時。
這樣不行必須優化循環,減少時間複雜度。
第二次提交
只看n,n每次整除5,得到的是1-n這些數裏面能夠提供5的個數
然後再次對n除5,得到的是剩下的數中還能再提供5的個數, 直到 n=0
int ans = 0;
while(n){
ans += n/5;
n = n/5;
}
這樣時間複雜度爲O(log5(n))而不是O(n/5).
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<inttypes.h>
using namespace std;
int64_t sumzero(int64_t n)
{
int ans=0;
//Z = N/5 + N /(5*5) + N/(5*5*5)…..直到N/(5的K次方)等於0
//公式中 N/5表示不大於N的數中能被5整除的數貢獻一個5,N/(5*5)表示不大於N的數中能被25整除的數再貢獻一個5
while(n){
ans += n/5;
n = n/5;
}
return ans;
}
int main()
{
int64_t n,m;
while(cin>>n){
for(int i=1;i<=n;i++){
cin>>m;
cout<<sumzero(m)<<endl;
}
}
return 0;
}
通過這個題,能夠學到一點點編程小技巧,計算思維+降低時間複雜度。