【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
");
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
",ans);
}
return 0;
}