问题:给出两个数$N(1\le N\le 10^{9})$和$B(2\le B\le 100000)$,求解$N!$以$B$为基表达时末尾$0$的个数。
例子:(1)$7!$以$10$为基时等于$5040$,此时末尾有$1$个$0$.
(2)$7!$以$2$为基时表示为$1001110110000$,此时末尾有$4$个$0$.
分析:以$B$为基时,$N!$中末尾$0$的个数就等于$N!$能被$B$整除的次数。所以我们先对$B$做素因子分解,如下所示
$p_{1}, x_{1}$
$p_{2}, x_{2}$
$\dots$
$p_{k}, x_{k}$
即$B=p_{1}^{x_{1}}p_{2}^{x_{2}}\dots p_{k}^{x_{k}}$,然后根据勒让德定理,分别取得$N!$对应素因子$p_{1},p_{2},\dots,p_{k}$的个数$y_{1},y_{2},\dots,y_{k}$,则
$N!$能被$B$整除的次数为
$\min\{\frac{y_{1}}{x_{1}},\frac{y_{2}}{x_{2}},\dots,\frac{y_{k}}{x_{k}}\}$.
代码:
#include
#include
#include
#include
using namespace std;
int num[100005];
int prime[9593];
int pnT;
void sieve(int n)
{
int i, j;
memset(num, 0, sizeof(num));
int m = sqrt(0.5 + n);
for (i = 2; i <= m; i++)
if (!num[i])
for (j = i*i; j <= n; j += i)
num[j] = 1;
pnT = 0;
for (i = 2; i <= n; i++)
if (num[i] == 0)
{
pnT++;
prime[pnT] = i;
}
}
int pTab[7][2];
int nNum;
void pnF(int n)
{
int i;
nNum = 0;
int temp;
for (i = 1; i <= pnT; i++)
{
if (n < prime[i])
break;
if (n%prime[i] == 0)
{
nNum++;
pTab[nNum][1] = prime[i];
temp = 0;
while (n%prime[i] == 0)
{
n /= prime[i];
temp++;
}
pTab[nNum][2] = temp;
}
}
}
int n_p(int n,int p)
{
int count = 0;
while (n >= p)
{
count += n / p;
n /= p;
}
return count;
}
int main()
{
int N, B;
sieve(100000);
int i;
int ans;
while (~scanf("%d%d", &N, &B) && N)
{
ans = 0x3f3f3f3f;
pnF(B);
for (i = 1; i <= nNum; i++)
ans = min(ans, n_p(N, pTab[i][1]) / pTab[i][2]);
printf("%d\n", ans);
}
return 0;
}
View Code
标签:dots,le,2763,SOJ,int,num,阶乘,include,末尾
来源: https://www.cnblogs.com/ClearMoonlight/p/10579255.html