zero(NOIP模拟赛 Round 4)
题目描述
假设x=N!,那么x的末尾有多少个零呢?
输入
一行,一个整数N。
输出
输出只有一个整数,表示x末尾零的个数。
这道题目,我们看一看数据范围,
10^1000肯定是高精啦!
然后我们再想一想如何计算多少个0
我们可以肯定0=2*5(好吧,只是递推式),并且2的数量一定比5多
所以我们只需要计算N!中含有多少个5
然后我们列个表5 10 15 20 25 30 35 40 45 50
1 1 1 1 2 1 1 1 1 2
很显然5的个数就可以得到递归式:
while(num)
{
num/=5;ans+=num;
}
然后贴一下代码经验:
如果像我写的一样,在函数中调用字符数组的指针,那么我们如果要将这个数组清空,不能用memset而要for一遍,并且要提前记录strlen(a)因为你在清零的时候,strlen(a)不是定值!!
再说一遍
调用指针数组时不能用memset!!!
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char qaq[100001]; char ans[100001]; int num1[100001],num2[100001]; void gjj(char a[],char b[]) { memset(num1,0,sizeof(num1)); memset(num2,0,sizeof(num2)); int l1=strlen(a),l2=strlen(b),l; for(int i=0;i<=l1-1;i++) num1[l1-i-1]=a[i]-'0'; for(int i=0;i<=l2-1;i++) num2[l2-i-1]=b[i]-'0'; if(l1>l2)l=l1; else l=l2; for(int i=0;i<=l-1;i++) { num1[i]+=num2[i]; if(num1[i]>=10)num1[i+1]++,num1[i]-=10; } while(num1[l])l++; for(int i=l-1;i>=0;i--) a[l-i-1]=num1[i]+48; } void div(char a[],int b) { int r[100001]; memset(r,0,sizeof(r)); int num=-1; int d=0; for(int i=0;i<strlen(a);i++) { r[++num]=(d*10+a[i]-'0')/b; d=(d*10+(a[i]-'0'))%b; } int p=0; int qs=strlen(a); for(int i=0;i<qs;i++) a[i]=0; for(int i=0;i<=num;i++) if(!r[i])++p;else break; int tot=-1; for(int i=p;i<=num;i++) { a[++tot]=r[i]+'0'; } } int main(){ freopen("zero.in","r",stdin); freopen("zero.out","w",stdout); scanf("%s",qaq); ans[0]='0'; while(1) { div(qaq,5); if(!strlen(qaq))break; gjj(ans,qaq); } printf("%s\n",ans); fclose(stdin); fclose(stdout); }