题目背景
数据已修改
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且k≠1
首先,我们可以知道,一个数改成k进制后,他末尾为0的个数为该数能整除k的次数
然后,我们就可以想到,把k分成质因子以及其出现个数
对于每一个质因子,我们从x的阶乘中找出1~x中可以分解出多少个质因子,然后将得到的答案/改质因子出现的次数,取min值,最后即为答案
对于从1~x中找出能分解出质数y的个数可以用不断重复x/=y直至x==0,x分别表示从1~x中y^1,y^2,y^3……的倍数出现的个数
然而,知道了这些的我依然不会做,╮(╯▽╰)╭,所以,求大佬帮我看一下哪个地方弄错了
#include
#include
#define ll long long
using namespace std;
ll n,m,tot,up,cnt,now,w,ans;
ll prime[500005],q[100005],t[100005];
bool vis[1000005];
ll min(ll x,ll y)
{
if (x<y) return x; else return y;
}
int main()
{
scanf("%lld%lld",&n,&m);
up=trunc(sqrt(m));tot=0;cnt=0;
for (ll i=2;i<=up+4;i++)
{
if (!vis[i]) prime[++tot]=i;
for (ll j=1;j<=tot&&prime[j]*i<=up+4;j++)
{
vis[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
for (ll i=1;prime[i]<=up+4&&m!=1;i++)
{
if (m%prime[i]==0)
{
q[++cnt]=prime[i];
while (m%prime[i]==0) t[cnt]++,m/=prime[i];
}
}
ans=1e18;
if (m>1) prime[++cnt]=m,t[cnt]++;
for (ll i=1;i<=cnt;i++)
{
now=0;w=n;
while (w!=0) now+=w/q[i],w/=q[i];
ans=min(now/t[i],ans);
}
printf("%lld\n",ans);
return 0;
}