2023牛客暑期多校训练营6(C-idol!!)

题目链接:

C-idol!!_2023牛客暑期多校训练营6 (nowcoder.com)

题目大意:

求解:1!!* 2!!······ n!! 的值末尾0的个数;

题意转化:

末尾0的个数就是几个10的相乘,就是10的个数,由于10=2*5,所以就是求解质因数2和5的个数;但由于2一定比5多,所以就直接转化为求解5的个数;

比赛的时候想到了等差数列求解5的个数,竟然没想到5的次方的个数咋求解;

题解思路:

先说下如何采用等差数列求解5的个数;

分两种情况:求解奇数中5的个数,求解偶数中5的个数

对于奇数:

对于偶数:

暂时先不考虑5的次方的情况(就是一个数中包含几个5的情况,比如说25)很容易看出来就是首项为5,公差为5的等差数列;

所以单纯求5的个数的代码如下:

void solve()
{
    cin>>n;
    int sum1=n/2+1-2,sum2=n/2-4;//求需要求的奇数和偶数的个数

    int cnt1=sum1/5,cnt2=sum2/5;//求等差数列求和的项数
    int n1=sum1%5,n2=sum2%5;//单独多出来的几项

    int ans1=0,ans2=0;
    ans1+=5*(1+cnt1)*cnt1/2,ans2+=5*(1+cnt2)*cnt2/2;//等差数列求和,首项加末项乘以项数除以2
    ans1+=(cnt1+1)*n1,      ans2+=(cnt2+1)*n2;      //加上多余的几项,多余的几项肯定比前几项最后一个大一

    if(sum1<0) ans1=0;
    if(sum2<0) ans2=0;

    cout<<ans1+ans2<<endl;
}

再思考要是有25,50,75,125一个数中含有多个5的情况,该如何求解;

例如:对于25以后的数都会含有25,多以都会含有5^2;一下只考虑5^2的情况的个数为

举完例子后发现是25个数后才会多出一个5^2,因为这时候才会出现一个25的倍数,

这种情况就为以25为首项,25为公差的等差数列;同理可得偶数的情况也是同样的;

那么只需要求解5,5^2,5^3 第一次出现的位置就可以了,然后用n-第一次出现的位置就知道对应的情况有多少个数了,然后同样用求解5的个数的方法求解其他情况即可;

代码如下:

#define int128 __int128_t
void print(int128 x){
     if(x<0)x=-x,putchar('-');
     if(x>9)print(x/10);
     putchar(x%10+'0');
}

int128 sub(int128 n,int128 k){
    int128 cur=1,w=1,ans=0;
    while(1){
        w*=5;
        cur=cur*5-k;//难点,这个可能比较难想到,但可以换种写法一样的,比如说偶数是w,奇数就是(w+1)/2,w就是上面那个w
        if(cur>n) break;
        int128 cnt=(n-cur+1)/w;
        int128 sum=(n-cur+1)%w;
        ans+=w*(1+cnt)*cnt/2;
        ans+=(cnt+1)*sum;
    }
    return ans;
}

void solve(){
    cin>>n;
    int128 ans=0;
    ans+=sub(n/2,0);
    ans+=sub((n+1)/2,2);
    print(ans);
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值