弱校胡策 银魂

来源:互联网 发布:淘宝禁售商品管理规范 编辑:程序博客网 时间:2024/05/19 15:41

题目来源

https://www.luogu.org/problem/show?pid=3927

题目描述

银桑、神乐、新八三人在测试阿姆斯特朗回旋加速喷气式阿姆斯特朗炮的威力。 阿姆斯特朗回旋加速喷气式阿姆斯特朗炮十分神奇,使用方式如下:
输入两个数字n,k到阿姆斯特朗回旋加速喷气式阿姆斯特朗炮的控制台中,然后阿姆斯特朗回旋加速喷气式阿姆斯特朗炮会计算出n!并把它转化为k进制。
最后n!在k进制下末尾0的个数就是本次发射的威力,每个0代表1点威力。 为了测试时不造成太大的破坏,三人想知道每次测试,发射的威力有多大。
现在给出多组测试的n和k,请计算出每次发射的威力。

输入描述 输入文件为amstl.in 题目包含多组数据,以EOF(文件结尾)为结束。 对于每组数据,输入一行两个正整数n,k;

输出描述 输出文件为amstl.out 每组数据一行,包含一个整数,表示本次发射的威力。

样例输入
10 40
样例输出
2

数据范围:
对于 30%的数据, n <= 1000000, k = 10
对于另外 10%的数据, n <= 20, k <= 20
对于另外 20%的数据, n <= 50, k <= 52
对于另外 10%的数据, n<=10^12, k = 2
对于 100%的数据, n <= 10^12, k <= 10^12

题目解释:求 n!在 k 进制下末尾 0 的个数

正解:这个题求n!在k进制下末尾0的个数,其实就是求在n!中%k=0出现的情况。首先这个数据范围很大所以我们考虑对N!,k进行质因数分解。分解N!利用原来说过的
f(α)=n/α+n/α^2+…+n/α^k (α^k<=n)这个式子全是下取整,复杂度大约是logN。枚举2~根号k,对于k的每个质数,我们都统计出在k中的出现次数,再利用上面讲的思想,logN求出N!中的个数,相除就是这个因子出现的0的个数,然后每次都取min,得到最优的答案。(正确性:类似于木桶原理,也就是决定0的个数出现的次数,只取决于答案最小的因子,因为大小因子都有才能组合成k)

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const long long maxn=1e16+8;int main(){    long long ans;    long long n,k,cnt1,cnt2;    while(scanf("%lld%lld",&n,&k)!=EOF)    {        ans=maxn;        long long shu=sqrt(k)+1;        for(int i=2;i<=shu;i++)        {            cnt1=0,cnt2=0;            while(k%i==0){                cnt1++;                k/=i;            }            if(cnt1==0) continue;            long long q=i;            while(q<=n)            {                cnt2+=(n/q);                q*=i;            }            ans=min(ans,cnt2/cnt1);        }        cnt2=0;        if(k>1)        {            long long q=k;            while(q<=n)            {                cnt2+=(n/q);                q*=k;            }            ans=min(ans,cnt2);        }        if(ans==maxn) ans=0;        printf("%lld\n",ans);       }    return 0;}