弱校胡策 银魂

题目来源

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
#include
#include
#include
#include
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;
}

你可能感兴趣的:(====数论====,=====复习=====,===弱校胡策===)