题目背景
不告诉你……
题目描述
求出1!*2!*3!*4!*……*n!的末尾有几个零
输入输出格式
输入格式:
n(n<=10^8)
输出格式:
有几个零
输入输出样例
输入样例#1: 复制
10
输出样例#1: 复制
7
首先末尾有0肯定就是乘10,10可以分解为2和5,显然2的数目多于5,于是就是统计5的数目
然后可以转化一下,
对于
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
……
1 2 3 4 5 6 …… x
我们来除一下5,发现能被5整除的项变成了:
1
1
1
1
1
1 2
1 2
1 2
1 2
1 2
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
……
1 2 3 4 5 …… x/5
1 2 3 4 5 …… x/5
1 2 3 4 5 …… x/5
1 2 3 4 5 …… x/5
1 2 3 4 5 …… x/5
也就是5个
1
1 2
1 2 3
……
1 2 3 4 5 …… x/5
这样就可以递归求解了
另外,这次除5总共除掉了5+10+15+20+(n/5)*5个,可以用等差数列公式
对于x应该是从5k+4开始的,多余的处理掉即可 时间复杂度O(logn)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #define ll long long 6 using namespace std; 7 int n; 8 ll work(int x){ 9 ll ret=0; 10 for(int i=5;i<=x;i*=5){ 11 ret+=x/i; 12 } 13 return ret; 14 } 15 ll find(int x){ 16 if(x<5){ 17 return 0; 18 } 19 if(x<10){ 20 return (x-4); 21 } 22 ll ret=0; 23 while((x+1)%5){ 24 ret+=work(x); 25 x--; 26 } 27 ret+=1LL*5*(x/5)*(1+(x/5))/2; 28 ret+=5*find(x/5); 29 return ret; 30 } 31 int main() 32 { 33 scanf("%d",&n); 34 printf("%lld\n",find(n)); 35 return 0; 36 }
时间: 2024-10-08 00:53:18