求N!後面有多少個0

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;
}

通過這個題,能夠學到一點點編程小技巧,計算思維+降低時間複雜度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章