Loading

【GDKOI2014】JZOJ2020年8月13日提高组T1 阶乘

【GDKOI2014】JZOJ2020年8月13日提高组T1 阶乘

题目

Description

在这里插入图片描述

Input

第一行有一个正整数T,表示测试数据的组数。
接下来的T行,每行输入两个十进制整数n和base。

Output

对于每组数据,输出一个十进制整数,表示在base进制下,n!结尾的零的个数。

Sample Input

2
10 10
10 2

Sample Output

2
8

Data Constraint

对于20%的数据,n<=20,base<=16
对于50%的数据,n<=109,base<=105
对于100%的数据,1<=T<=50,0<=n<=1018,2<=base<=1012

题解

题意

给出\(n\)\(base\),求\(n\)的阶乘在\(base\)进制下末尾0的个数

分析

很显然可以先将\(base\)质因数分解
\(base\)拆成\(p1^{k1}*p2^{k2}*……\)的形式
记录底数和指数
然后对于每个质数
\(n\)一直除以\(p\),把每次的商加起来
除以指数,取个最小值即为答案

Code

#include<bits/stdc++.h>
#define rg register
#define MAX 1000000
#define inf 999999999999999
using namespace std;
long long t,n,m,i,x,num,sum,ans,prime[1000005],tot[1000005];
bool b[1000005];
int main()
{
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
    memset(b,true,sizeof(b));
    b[1]=false;
    for (rg long long i=2;i<=MAX;i++)
        for (rg long long j=2;i*j<=MAX;j++)
            b[i*j]=false;
    scanf("%lld",&t);
    while (t--)
    {
        scanf("%lld%lld",&n,&m);
        if (n==0) 
        {
            printf("0\n");
            continue;
        }
        num=0;
        memset(prime,0,sizeof(prime));
        memset(tot,0,sizeof(tot));
        for (rg long long i=2;i*i<=m;i++)
        {
            if (b[i]==true&&m%i==0)
            {
                num++;
                prime[num]=i;
                while (m%i==0)
                {
                    tot[num]++;
                    m/=i;
                }
            }
        }
        if (m>1)
        {
            num++;
            prime[num]=m;
            tot[num]=1;
        }
        ans=inf;
        for (rg long long i=1;i<=num;i++)
        {
            x=n;
            sum=0;
            while (x)
            {
                sum+=x/prime[i];
                x/=prime[i];
            }
            sum/=tot[i];
            ans=min(ans,sum);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2020-08-13 16:50  Thunder_S  阅读(169)  评论(0编辑  收藏  举报