首页 > 代码库 > zero(NOIP模拟赛 Round 4)

zero(NOIP模拟赛 Round 4)

原题传送门

这道题目,我们看一看数据范围,

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

 

zero(NOIP模拟赛 Round 4)