P3927 SAC E#1 - 一道中档题 Factorial

https://www.luogu.org/problemnew/show/P3927

题目背景

数据已修改

SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友。

题目描述

SOL君很喜欢阶乘。而SOL菌很喜欢研究进制。

这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘。

SOL菌表示不服,立刻就要算这个数在k进制表示下末尾0的个数。

但是SOL菌太菜了于是请你帮忙。

输入输出格式

输入格式:

每组输入仅包含一行:两个整数n,k。

输出格式:

输出一个整数:n!在k进制下后缀0的个数。

cf遇到的一题,后来听说luogu上有原题。当时想出来了但是没时间写,现在补一下。

分析:

要想有0,那么肯定是有因子k,同时,k的个数也就是k的个数。那么就是求n!里因子k的个数咯。可以考虑将k质因数分解。设一个质因子为x,x的指数为t(唯一分解)那么k的个数就为min(n!里x的个数/t)。然后就是解决求n!里x的个数。n!里x的个数=n!/x+n!/x*x+n!/x*x*x....。就解决了这个问题。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<algorithm>
#include<cmath>
#define rg register
#define il inline
using namespace std;
typedef unsigned long long ll;
ll read(){
    ll ans=0,flag=1;char ch;
    while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
    ans=ch^48;
    while((ch=getchar())>='0'&&ch<='9') ans=(ans<<3)+(ans<<1)+(ch^48);
    return flag*ans;
}
void write(ll x){
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
struct factor{
    int val,cnt;
    factor(int val,int cnt):val(val),cnt(cnt){}
};
int main(){
    ll n=read(),k=read(),cnt;
    queue<factor> q;ll t=k;
    for(rg ll i=2;k!=1&&i*i<=t;i++){
        if(k%i==0){
            cnt=0;
            while(k%i==0){
                cnt++;
                k/=i;
            }q.push(factor(i,cnt));
        }
    }
    if(k>1) q.push(factor(k,1));
    ll ans=1e12;
    while(!q.empty()){
        factor f=q.front();q.pop();
        long long t=0,now=n;
        while(now)t+=now/=f.val;
        t/=f.cnt;
        if(t<ans)ans=t;
    }
    cout<<ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ffscas/article/details/87868636