Wannafly挑战赛25A——质因子分解

题目链接:Wannafly挑战赛25A

题目总结:哇,还真是质因子筛选!考试的时候想到了质因子个数相除,但不知道一个阶乘该如何计算出一个因子的个数......

求一个大数n的阶乘的所含因子p的个数,我们知道,

n!=1*2*3*4*......n

为求出p的个数,将上式表示为

n!=(p*2p*3p*4p*......*kp)*q,其中q就是其他不是因子p的倍数的乘积,比如10!=(2*(2*2)*(3*2)*......(5*2))*q,q是不含p的可以不管,k=n/p;

这样,我们可以提出k个p出来,原式为

n!=p^k*k!*q,再将k!像上面的方法一样分解,就可以得到p的个数

代码如下:

//阶乘因子分解,找出n!中有多少个p
ll findnum(ll n,ll p)
{
    ll ans=0;//个数
    if(k==0)return 0;
    while(n)
    {
        ans+=n/p;//一次变换后的个数
        n/=p;//将k=n/p再迭代
    }
    return ans;
}

那么,我们就可以将给定的p进行质因子分解,找出质因子和它们的个数,再用上述方法找到n!中p的每个质因子的个数,找到两者相除的最小值就是答案。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;

typedef long long ll;
/*
     筛出p的最小质数和个数,再用快速算法求出n!中含有多少个最小质数
     两者个数相处就得到答案k
     快速求N!中有多少质数m的算法就是迭代公式
*/

const ll maxn=10001;
int isprime[maxn];
int notprime[maxn];
ll n_num[maxn];//n的每个质因子个数
ll p_num[maxn];//p的每个质因子个数

int cnt;

//筛选质数
void eular()
{
    memset(isprime,0,sizeof(isprime));
    memset(notprime,0,sizeof(notprime));
    cnt=0;
    for(int i=2;i<maxn;i++)
    {
        if(!notprime[i])
        {
            isprime[++cnt]=i;
        }
        for(int j=1;j<=cnt&&i*isprime[j]<maxn;j++)
        {
            notprime[i*isprime[j]]=1;
            if(i%isprime[j]==0)
                break;
        }
    }
}

//阶乘因子分解,找出n!中有多少个p
ll findnum(ll n,ll p)
{
    ll ans=0;
    while(n)
    {
        ans+=n/p;
        n/=p;
    }
    return ans;
}

int main()
{
    ll n,p;
    eular();
    int tot=1;
    while(scanf("%lld%lld",&n,&p)!=EOF)
    {
        memset(n_num,0,sizeof(n_num));
        memset(p_num,0,sizeof(p_num));
        while(p!=1)
        {
            //求p的每个质因子的个数
            while(p%isprime[tot]==0&&p)
            {
                p_num[tot]++;
                p/=isprime[tot];
            }
            tot++;
        }
        for(int i=1;i<=tot;i++)
        {
            n_num[i]=findnum(n,isprime[i]);
        }
        ll ans=2e18+5;
        for(int i=1;i<=cnt;i++)
        {
            if(p_num[i])
                ans=min(ans,n_num[i]/p_num[i]);//找一个最小的因子数之商
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Q755100802/article/details/82895831
今日推荐