洛谷10月月赛R1·浴谷八连测R1·提高组 SAC E#1 - 一道中档题 Factorial

30 篇文章 0 订阅
9 篇文章 0 订阅

题意:求 n! k 进制下后缀0的个数。

老夫掐指一算,竟然掐到std算法?

  • Solution
    讲道理,刚开始看到这道题是不会做的。
    但是老夫想想如果 m=10 还是会做的。
    数数小于等于 n 有多少个5的倍数就行了。2的倍数绝对比5的倍数多嘛。
    于是我就有了一点想法。
    首先质因数分解少不了的。m=ki=1scntii
    然后,对于每个质因数 si ,算一算 [1,n] 能找到多少它的倍数(不过类似计算2时遇到 23 这些要算三次的)
    怎么计算?容斥一下?应该只有我这种zz一开始这么想?
    后来发现计算的时候每次加1就行了,因为前面的都已经计算过了。
    算完之后,发现 si [1,n] 中找到了 xi ,但是出现一个 m 至少si要出现 cnti 次。所以最终答案就是 minki=1{xicnti}
#include <bits/stdc++.h>
#define LL long long
using namespace std ;
LL n, m, tot ;
LL s[1010], cnt[1010] ;
int main() {
#ifndef ONLINE_JUDGE
    freopen ( "a.in", "r", stdin ) ;
    freopen ( "a.out", "w", stdout ) ;
#endif
    LL i, j, x, ans, gn ;
    while ( scanf ( "%lld%lld", &n, &m ) != EOF ) {
        memset ( s, 0, sizeof s ) ;
        memset ( cnt, tot = 0, sizeof cnt ) ;
        for ( x = m, i = 2 ; i*i <= x ; i ++ ) {
            if (x%i == 0) s[++tot] = i ;
            while (x%i == 0) cnt[tot] ++, x /= i ;
        }
        if (x != 1) s[++tot] = x, cnt[tot] = 1 ;    
        /*printf ( "%lld = ", m ) ;
        for ( i = 1 ; i < tot ; i ++ ) printf ( "%lld^%lld + ", s[i], cnt[i] ) ;
        printf ( "%lld^%lld\n", s[tot], cnt[tot] ) ;*/
        ans = 1LL<<60 ;
        for ( i = 1 ; i <= tot ; i ++ ) {
            gn = 1 ;    
            x = 0 ; 
            for ( j = 1 ; gn <= n ; j ++ ) {
                gn *= s[i] ;
                x += n/gn ;
            }
            //printf ( "time %lld = %lld\n", s[i], x ) ;    
            ans = min(ans, x/cnt[i]) ;  
        }
        printf ( "%lld\n", ans ) ;  
    }
    return 0 ;
}

恬不知耻的发个广告:我的博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值