【GDKOI2014】阶乘
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
反思&题解
比赛&正解思路: 我们回忆一下转进制的过程,答案就是
一直除以base的余数开始连续0的个数,所以我们很自然地就想到了分解质因数,首先我们先将base分解一下质因数,对于每一个质因子去处理,假设当前处理2这个质因子,n等于是10,我来模拟一下这个过程(下面的除法都取整除):
首先10以内包含1个2的:2,4,6,8,10 共5个 ——— 10/2=5(个)
包含2个2的:4,8,共2个 ——— 5/2=2(个)
包含3个2的,8,共1个 ——— 2/2=1(个)
之后
里面一共可以取出5+2+1=8个2
对于每个质因子都进行这样的操作计算出一共可以取出多少个,再去整除从base里面分解出来的这个质因子的个数,得到的所有商取最小的就行了,因为同时都包含的相对个数的商才是合法的答案(这应该很好理解吧)
反思: 终于靠着自己的分析做出一道数学题了 (我太弱了(ノ=Д=)ノ)
CODE
#include<bits/stdc++.h>
using namespace std;
long long const inf=1e17;
long long t,n,base,zyz[1000005],num[1000005],ans;
int main()
{
scanf("%lld",&t);
while (t--)
{
memset(zyz,0,sizeof(zyz));
memset(num,0,sizeof(num));
scanf("%lld%lld",&n,&base);
long long base1=base,i;
for (i=2;i<=sqrt(base1);i++)
{
if (base==1) break;
if (base%i==0)
{
num[++num[0]]=i;
while (base%i==0)
{
zyz[num[0]]++;
base/=i;
}
}
}
if (base>1)
{
num[++num[0]]=base;
zyz[num[0]]=1;
}
ans=inf;
for (i=1;i<=num[0];i++)
{
long long nn=n,tot=0;
while (nn>0)
{
nn/=num[i];
tot+=nn;
}
if (tot/zyz[i]<ans) ans=tot/zyz[i];
}
printf("%lld\n",ans);
}
return 0;
}