题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3988
题意:给出n,k,找出最大的i,满足 n!%k^i。
题解:我们先对k进行质因子分解,假设p是k的一个质因子,那么我们先算出p在k中出现的次数tt,然后算出在n中出现的次数num,此时 i 最大为num/tt,故我们就一直找k的质因子,每次取 num/tt的最小值。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn=1e7+10;
#define INF 0x3f3f3f3f
int pri[maxn],cnt;
bool vis[maxn];
void init()
{
memset(vis,0,sizeof(vis));
cnt=0;
for(int i=2;i<maxn;i++)
{
if(!vis[i]) pri[++cnt]=i;
for(int j=1;j<=cnt&&i*pri[j]<maxn;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
}
LL get_sum(LL n,LL p) ///算出质数p在n!中有多少个
{
LL res=0;
while(n)
{
n/=p; ///说明前n个中有n/p个数被p整除
res+=n;
}
return res;
}
int main()
{
init();
int ncase,T=0;
scanf("%d",&ncase);
LL n,k;
while(ncase--)
{
scanf("%lld%lld",&n,&k);
if(k==1){
printf("Case %d: inf\n",++T);
continue;
}
LL ans=-1;
int i=1;
while(pri[i]<=k&&i<=cnt) ///质因子分解
{
LL tt=0;
if(k%pri[i]==0){
while(k%pri[i]==0)
{
k/=pri[i];
tt++;
}
LL item=get_sum(n,(LL)pri[i])/tt;
if(ans==-1) ans=item;
else ///每次取最小
ans=min(ans,item);
}
i++;
}
if(k>1){
LL item=get_sum(n,k);
if(ans==-1) ans=item;
else
ans=min(ans,item);
}
printf("Case %d: %lld\n",++T,ans);
}
return 0;
}