light oj 1090 Trailing Zeroes (II)

/*

1)改题:刚开始看错题目了,把题目看成求这个数的位数,然后就错了,不过如果把题目改成求C(n,r)*p^q的位数,也是

一个不错的小题目。那样的话就用到了:
    1)用log(base)n+1 求n在base进制下的位数.
    2)log换底公式和其它一些简单公式。代码如下:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define maxn 1000005
double fac[maxn];
void get_fac(){              //记录{ log1,...logn }前i项的和
    fac[0]=0;
    for(int i=1;i<maxn;i++){
        fac[i]=fac[i-1]+log(i*1.0);
    }
}
int main(){
    int i,j,n,t,r,p,q;
    get_fac();
    cin>>t;
    for(i=1;i<=t;i++){
        scanf("%d%d%d%d",&n,&r,&p,&q);
        int ans=(int)((fac[n]-fac[n-r]-fac[r]+q*log(p*1.0))/log(10.0))+1;
        printf("Case %d: %d\n",i,ans);
    }
    return 0;
}


2) 这道题目是求有几个后缀0,想了一下,刚开始想的是可以把这个式子分解成好多项相乘,要出现一个10,则个位为 2*5, 4*5, 6*5, 8*5 或者看末位有几个0.所以对一个数,
首先看这个数的末位有几个0,这样的话进位问题会出错,于是有进一步考虑了下,知道了思路:10=2*5.这样就不用考虑进位问题了,所以问题转化为求每个数中可以因式分解
出几个2和几个5,然后看这个式子中总共有几个2和5就可以解决问题,所以预处理1-1000000中每个数有几个2和5,因为2^20,5^9就足够,所以暴力时间复杂度就够了。剩下的
就简单了。




后来看别人的题解,发现他直接求n!的x因子的算法挺巧妙的,就摘过来了:
int fac(int x , int y){//x!的y因子的个数
    int s = 0  ;
    while(x){
        s += x/y ;
        x /= y ;
    }
    return s ;
}

*/

下面是我的程序:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 1000005
int num2[maxn],num5[maxn],fac2[maxn],fac5[maxn];
//求出每个数2和5这两个因子的个数
void get_num(){
    memset(num2,0,sizeof(num2));
    memset(num5,0,sizeof(num5));
    for(int i=1;i<maxn;i++){
        if(i%2==0){
            int k=i;
            while(k%2==0){num2[i]++; k/=2;}
        }
        if(i%5==0){
            int k=i;
            while(k%5==0){num5[i]++; k/=5; }
        }
    }
}
//打表出前i个数中一共含有几个2和5,存在fac数组中
void get_fac(){
    fac2[0]=0; fac5[0]=0;
    for(int i=1;i<maxn;i++) {
        fac2[i]=fac2[i-1]+num2[i];
        fac5[i]=fac5[i-1]+num5[i];
    }
}
int main(){
    int i,j,n,t,r,p,q;
    get_num();
    get_fac();
    cin>>t;
    for(i=1;i<=t;i++){
        scanf("%d%d%d%d",&n,&r,&p,&q);
        int n2=fac2[n]-fac2[n-r]-fac2[r]+q*num2[p];
        int n5=fac5[n]-fac5[n-r]-fac5[r]+q*num5[p];
        int ans=min(n2,n5);
        printf("Case %d: %d\n",i,ans);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值