题目背景
数据已修改
SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友。
题目描述
SOL君很喜欢阶乘。而SOL菌很喜欢研究进制。
这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘。
SOL菌表示不服,立刻就要算这个数在k进制表示下末尾0的个数。
但是SOL菌太菜了于是请你帮忙。
输入输出格式
输入格式:
每组输入仅包含一行:两个整数n,k。
输出格式:
输出一个整数:n!在k进制下后缀0的个数。
输入输出样例
输入样例#1:
10 40
输出样例#1:
2
说明
对于20%的数据,n <= 1000000, k = 10
对于另外20%的数据,n <= 20, k <= 36
对于100%的数据,n <= 10^12,k <= 10^12
update
1.一组数据
2.K不会==1
3.现在std没有爆long long
4.对数据有问题联系icy (建议大家不要面向数据编程)
解题报告
我们不难发现,一个数能够连续整除多少个k,他的k进制表示法末尾就会有多少个0。那么这道题也就转化为了问我们
!n
能够连续整除多少个k。
我们先给k分解质因数,对于一个质因数p,求出
!n
中有多少个p,再把这个值与p在k中出现的次数相除就好了。
那么问题就在如何求出
!n
中有多少个p上。我们知道,如果n足够大,那么
!n=1×2×3×4×...×(p−1)×p×...×(2p−1)×2p×...×n
,可见,我们只需要数出n能够被p整除几次就好了。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1000000;
ll prime[N+5],cnt[N+5],num;
ll n,k,ans;
int main()
{
scanf("%lld%lld",&n,&k);
for(ll i=2;i*i<=k;i++)
if(k%i==0)
{
prime[++num]=i;
cnt[num]=0;
while(k%i==0)++cnt[num],k/=i;
}
if(k>1)prime[++num]=k,cnt[num]=1;
ans=2e12;
for(int i=1;i<=num;i++)
{
ll temp=0,u=n;
while(u)u/=prime[i],temp+=u;
temp/=cnt[i];
ans=min(ans,temp);
}
printf("%lld",ans);
return 0;
}