首先,这道题不可能直接算n!和a^k然后暴力解法,数太大了。那就乖乖找规律吧。
以输入n=6,a = 10,为例。
6! =
2
×
2
×
2
×
2
×
3
×
3
×
5
2\times2\times2\times2\times3\times3\times5
2×2×2×2×3×3×5,
10 =
2
×
5
2\times5
2×5,
如果6!可以被10^k整除,那么6!的素因数一定包含10的素因数,那么k就 =6!与10的相同素因数中,个数最少的那个素因数的个数。
6!与10的相同素因数有2和5,6!中2的数量是4个,5的数量是1个,故此例的k = 1。
以n=10,a=10为例再看一遍:
首先都分别筛选素因数
10! =
2
×
2
×
2
×
2
×
2
×
2
×
2
×
2
×
3
×
3
×
3
×
3
×
5
×
5
×
7
2\times2\times2\times2\times2\times2\times2\times2\times3\times3\times3\times3\times5\times5\times7
2×2×2×2×2×2×2×2×3×3×3×3×5×5×7;
10 =
2
×
5
2\times5
2×5;
看到10!和素因数有2,3,5,7,是包含10的所有素因数2和5的,故可以整除,在2和5中,素因数2的个数为8个,素因数5的个数为2个,故k = 2。
晚上迷迷糊糊敲的,好多其实不必要,懒得改了
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
const int maxn = sqrt(1000)+1;
typedef struct
{
int prime;
int num;//对应素因数的个数,也就是幂指数
} primearray,*pa;
void initial(vector<int>&prime)//用筛除法求出素数列表
{
bool isPrime[maxn];
for(int i = 0; i<maxn; i++)
{
isPrime[i] = true;
}
isPrime[0] = false;
isPrime[1] = false;
for(int j = 2; j<maxn; j++)
{
if(!isPrime[j])
continue;
prime.push_back(j);
for(int k = j*j; k<maxn; k += j)
{
isPrime[k] = false;
}
}
}
vector<primearray> getpa(vector<int>&prime,int x)//求出一个数所有的素因数,用num存储对应素因数个数
{
vector<primearray>pa;
int len = prime.size();
for(int i = 0; i<len && prime[i] <= x; i++)
{
bool isprime = false;
primearray pnode;
pnode.num = 0;
pnode.prime = prime[i];
while(x%pnode.prime == 0)
{
x /= pnode.prime;
isprime = true;
}
if(isprime)
pa.push_back(pnode);
}
return pa;
}
int main()
{
vector<int>prime;
int n,a,k=0;
while(scanf("%d%d",&n,&a) != EOF)
{
initial(prime);
vector<primearray>pa = getpa(prime,a);
int len = pa.size();
for(int i = 0;i<pa.size();i++)
{//因为无法直接拿n!来用,太大了,就从n一点点开始找同一个素因数,n找完了,就找n-1,最后到1,累加得到此素因数的个数
int nn = n;
while(nn>1)
{
int nt = nn;
while( nt % pa[i].prime == 0)
{
nt /= pa[i].prime;
pa[i].num++;
}
nn--;
}
}
k = pa[0].num;//找出最小的num
for(int j = 0;j<pa.size();j++)
{
if(pa[j].num == 0)
break;
int num = pa[j].num;
if(k > pa[j].num)
k = pa[j].num;
}
printf("%d\n",k);
}
return 0;
}