LuoguP3927 SAC E#1 - 一道中档题 Factorial 解题报告【唯一分解定理】

题目背景
数据已修改
SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友。
题目描述
SOL君很喜欢阶乘。而SOL菌很喜欢研究进制。
这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘。
SOL菌表示不服,立刻就要算这个数在k进制表示下末尾0的个数。
但是SOL菌太菜了于是请你帮忙。
输入输出格式
输入格式:
每组输入仅包含一行:两个整数n,k。
输出格式:
输出一个整数:n!在k进制下后缀0的个数。
输入输出样例
输入样例#1:
10 40
输出样例#1:
2
说明
对于20%的数据,n <= 1000000, k = 10
对于另外20%的数据,n <= 20, k <= 36
对于100%的数据,n <= 10^12,k <= 10^12
update
1.一组数据
2.K不会==1
3.现在std没有爆long long
4.对数据有问题联系icy (建议大家不要面向数据编程)
解题报告
我们不难发现,一个数能够连续整除多少个k,他的k进制表示法末尾就会有多少个0。那么这道题也就转化为了问我们 !n 能够连续整除多少个k。
我们先给k分解质因数,对于一个质因数p,求出 !n 中有多少个p,再把这个值与p在k中出现的次数相除就好了。
那么问题就在如何求出 !n 中有多少个p上。我们知道,如果n足够大,那么 !n=1×2×3×4×...×(p1)×p×...×(2p1)×2p×...×n ,可见,我们只需要数出n能够被p整除几次就好了。
代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1000000;
ll prime[N+5],cnt[N+5],num;
ll n,k,ans;
int main()
{
    scanf("%lld%lld",&n,&k);
    for(ll i=2;i*i<=k;i++)
    if(k%i==0)
    {
        prime[++num]=i;
        cnt[num]=0;
        while(k%i==0)++cnt[num],k/=i;
    }
    if(k>1)prime[++num]=k,cnt[num]=1;
    ans=2e12;
    for(int i=1;i<=num;i++)
    {
        ll temp=0,u=n;
        while(u)u/=prime[i],temp+=u;
        temp/=cnt[i];
        ans=min(ans,temp);
    }
    printf("%lld",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值