传送门
比赛的时候由于变量名打错了调了很久啊。
这道题显然是唯一分解定理的应用。
我们令
P
=
a
1
p
1
∗
a
2
p
2
∗
.
.
.
∗
a
k
p
k
P=a_1^{p_1}*a_2^{p_2}*...*a_k^{p_k}
P=a1p1∗a2p2∗...∗akpk。
那么对于每一个质因子
a
i
a_i
ai我们都可以计算出它在
n
!
n!
n!中出现
b
i
b_i
bi次,每次计算是
O
(
l
o
g
a
i
n
)
O(log_{a_i} n)
O(logain)的。
由于对于每个
P
P
P每个
a
i
a_i
ai会出现
p
i
p_i
pi次因此我们只需要取
m
i
n
min
min{
b
i
/
k
i
b_i/k_i
bi/ki}就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,p,ans=1e18;
inline ll calc(ll tmp){
ll mul=tmp,cnt=0;
while(mul<=n&&mul>0){
cnt+=n/mul;
mul*=tmp;
}
return cnt;
}
ll pri[100005],vis[10005],tot=0;
inline void init(){
for(int i=2;i<=p;++i){
if(!vis[i])pri[++tot]=i;
for(int j=1;j<=tot;++j){
int k=pri[j]*i;
if(k>p)break;
vis[k]=1;
if(i%pri[j]==0)break;
}
}
}
int main(){
cin>>n>>p,init();
ll len=sqrt(p);
for(ll i=1;pri[i]<=len;++i){
if(p%pri[i])continue;
ll siz=0;
while(p%pri[i]==0)++siz,p/=pri[i];
ans=min(ans,calc(pri[i])/siz);
}
if(p!=1)ans=min(ans,calc(p));
cout<<ans;
return 0;
}