一、题意
令 X = n!, 给定一大于1的正整数p 求一个k使得 p ^k | X 并且 p ^(k + 1) 不是X的因子
输入为两个数n, p (1e18>= n>= 10000 >= p >= 2)
二、分析
2.1前置知识:阶乘质因数分解
定理:在n!的标准分解式中,质因数p的指数h为
\[h = \left[ {\frac{n}{p}} \right] + \left[ {\frac{n}{{{p^2}}}} \right] + ... = \sum\limits_{r = 1}^\infty {\left[ {\frac{n}{{{p^r}}}} \right]} \]
推论:n!可以由他的质因数表示为
\[n! = \prod\limits_{p \le n} {{p^{\sum {\left[ {\frac{n}{{{p^r}}}} \right]} }}} \]
2.2本题思路
由题意可得,p的质因数肯定是n!的质因数;所以首先将p做质因数分解,得到p的各个质因数的指数h,再对每一个p的质因数求其在n!中的指数H
那么题中所求的K肯定是每一对H/h的数值中的最小值
\[ans = \arg \min \frac{{{H_i}}}{{{h_i}}}\]
三、代码
1 # include <iostream> 2 # include <cstdio> 3 using namespace std; 4 const long long INF = 1e18+10; 5 long long n,p; 6 long long H(long long i) 7 { 8 long long res = 0; 9 long long temp = n; 10 while(temp) 11 { 12 res += temp/i; 13 temp /= i; 14 } 15 return res; 16 } 17 void Solve() 18 { 19 long long ans = INF; 20 for(int i=2;i<=p;i++) 21 { 22 if(p%i == 0) 23 { 24 long long h = 0; 25 while(p%i==0) 26 { 27 h++; 28 p/=i; 29 } 30 ans = min(ans,H(i)/h); 31 } 32 } 33 printf("%lld\n",ans); 34 } 35 int main() 36 { 37 while(scanf("%lld%lld",&n,&p)!=EOF) 38 { 39 Solve(); 40 } 41 return 0; 42 }