题目背景
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
对于60%的数据,n <= 10^15,k <= 10^12
对于100%的数据,n <= 10^18,k <= 10^16
鬼题
如果k<=10^12是可以稳过的
k<=10^16就只剩pollard Rho(超出提高组模拟范围了)或玄学优化
首先k进制最后x位为0表示n!能整除k数x次(显然而重要的条件)
于是问题变为了n!含有多少个k的因子
k为合数不好处理,分解质因数k=p1^a1*p2^a2*p3^a3.....
对于求n!含k的数量,转变为求p1....的因子数,在除以a1...,取最小值
给出2种方法
1.
n!=(1k*2k*3k*4k*5k...mk)*a
=k^m*m!*a
a为不含k的积,m=n/k
这样就可以log递归求解
2.
含有一个k:n/k
含有二个k:n/k/k
.....
含有p个k:n/(k^p)
把它们相加
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #define count COUNT 7 using namespace std; 8 long long prime[100001],mi[100001],tot; 9 long long n,k,cnt,ans=9223372036854775807,s; 10 long long count(long long p,long long k,long long Mod) 11 { 12 long long num=0,ss=0; 13 while (p) 14 { 15 num+=p/k; 16 if (num>=Mod) ss+=1,num-=Mod; 17 p/=k; 18 } 19 return ss; 20 } 21 int main() 22 {register long long i; 23 while (scanf("%lld%lld",&n,&k)==2) 24 {tot=0;ans=9223372036854775807; 25 long long p=sqrt(k); 26 for (i=2;i<=p;i++) 27 { 28 if (k%i==0) 29 { 30 prime[++tot]=i; 31 cnt=0; 32 while (k%i==0) 33 { 34 k/=i; 35 cnt++; 36 } 37 mi[tot]=cnt; 38 } 39 if (k==1) break; 40 } 41 if (k!=1) 42 {tot++; 43 prime[tot]=k; 44 mi[tot]=1; 45 } 46 for (i=1;i<=tot;i++) 47 { 48 s=count(n,prime[i],mi[i]); 49 if (ans>s) ans=s; 50 } 51 printf("%lld ",ans); 52 } 53 }