素因子分解(SOJ 2763)

SOJ 2763: Factorial

问题:给出两个数$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<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
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

 

posted on 2019-03-22 16:44  小叶子曰  阅读(261)  评论(0编辑  收藏  举报

导航