/*
问题:给定n,a求最大的k,使得n!可以被a的k次方整除,但不能被a的k+1次方整除
输入:n(2<=n<=1000),a(2<=a<=1000)
6 10
输出:
1
6!=360.可以被10的1次方整除但是不能被10的2次方整除,
思路:累计除以k次为0,第k+1次不为0(错误)
1 a整除b,b/a 若a中存在素因数px ,则b也必存在该素因数,且该素因数在b中对应的幂指数不小于在a中的幂指数.
要求的k,只需要一次测试a中的每一个素因数,确定b中该素因数对应的幂指数是a栈中幂指数的几倍,所有倍数中最小的那个即为我们要求的k
2 对于a和n!分解素因数。n/(p*p)可以向n!提供两个p银子,但它们在之前(p的倍数必包括p*p的倍数)步骤中每个数都已经向计数器累加了1个p因子,此处
它们还能向计数器贡献n/(p*p)个素因子,累加器累加n/(p*p),若n/(p*p)=0,表示没有一个整数能够向n!提供2个或2个以上的p因子
3 一次遍历可能成为其素因子的素数,计算对应的幂指数,可完成对n!的素因数的分解
不懂
*/
#include <stdio.h>
#include <stdlib.h>
//#include <limits.h>
bool mark[1001];
int prime[1001];
int primeSize;
void init()
{
int i;
for(i = 1 ; i <= 1000 ; i++)//要注意初始值
{
mark[i] = false;//false表示素数
}
for(i = 2 ; i <= 1000 ; i++)//必须从2开始,否则就错了
{
if(true==mark[i])
{
continue;
}
prime[primeSize++] = true;
for(int j = i*i ; j <= 1000 ; j += i)
{
mark[j] = true;
}
}
}
int cnt[1001] = {0};//表示n!分解素因数之后,素因子prime[i]对应的幂指数,可能为0
int cnt2[1001] = {0};//表示prime[i]保存的素数在a中的因子数
int main(int argc,char* argv[])
{
_int64 n,a;
while(EOF!=scanf("%d %d",&n,&a))
{
int i;
//计数器清零
for(i = 0 ; i < primeSize ; i++)
{
cnt[i] = cnt2[i] = 0;
}
//对n!分解素因数,遍历从0到1000的素因数
for(i = 0 ; i < primeSize ; i++)
{
int t = n;//保存n
//依次计算t/prime[i]的k次方,累加其值,知道t/prime[k]的k次方为0
while(t)
{
cnt[i] += t/prime[i];//如果能整除就加1
t = t/prime[i];
}
}
//对a分解素因数,计算a中素因数prime[i]对应的幂指数
//int ans = long_max;
int ans = 123123123;
for(i = 0 ; i < primeSize ; i++)
{
while(a%prime[i]==0)
{
cnt2[i]++;
a /= prime[i];
}
//如果prime[i]不是a的素因数,直接跳过
if(0==cnt2[i])
{
continue;
}
//计算素数prime[i]在两个数中因子数的商
if(cnt[i]/cnt2[i] < ans)
{
ans = cnt[i]/cnt2[i];//统计这些商的最小值。因为k最大,所以n!与 a的共有素因数应该最小,次数之差即为
}
}
printf("%d\n",ans);
}
getchar();
return 0;
}