UVa 10780 幂和阶乘 求n!中某个因子的个数

题意:

输入两个整数m和n(m<5000,n<10000),求最大的整数k使得m^k是n!的约数

分析:

显然这题的做法是把m分解质因子,每个质因子的个数是cnt[i],然后求一下n!中m的质因子的个数num[i],那么答案就是ans=min(ans,num[i]/cnt[i])。求n!中某个因子的个数,因为n<10000,所以直接枚举每个数i(i< x)统计即可。

const int N=1e4+9;
vector<int>fac;
int cnt[N],num[N];
void prime_fac(int n)
{
    fac.clear();
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            fac.push_back(i);
            cnt[i]=1;
            n/=i;
            while(n%i==0)cnt[i]++,n/=i;
        }
    }
    if(n>1){
        fac.push_back(n);
        cnt[n]=1;
    }
}
int m,n,T;
int main()
{
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        memset(num,0,sizeof(num));
        memset(cnt,0,sizeof(cnt));
        scanf("%d%d",&m,&n);
        prime_fac(m);
        for(int i=2;i<=n;i++){
            for(int j=0;j<fac.size();j++){
                int x=i;
                while(x%fac[j]==0){
                    x/=fac[j];
                    num[fac[j]]++;
                }
            }
        }
        int ans=100000000;
        bool flag=1;
        for(int i=0;i<fac.size();i++){
            if(num[fac[i]]<cnt[fac[i]]){
                flag=0;break;
            }
            ans=min(ans,num[fac[i]]/cnt[fac[i]]);
        }
        printf("Case %d:
",cas);
        if(flag)printf("%d
",ans);
        else puts("Impossible to divide");
    }
    return 0;
}

做完这题后搜题解,看到大多数人都是用公式求n!中某个因子的个数,果然自己数论还是做得少啊!QAQ


求n!中某个因子的个数:

n!=(k^m)*(m!)*a 其中k是该因子,m=n/k,a是不含因子k的数的乘积

下面推导这个公式 :

n!=n*(n-1)*(n-2)*......3*2*1

  =(k*2k*3k.....*mk)*a      a是不含因子k的数的乘积,显然m=n/k;

  =(k^m)*(1*2*3...*m)*a

  =k^m*m!*a

接下来按照相同的方法可以求出m!中含有因子k的个数。

因此就可以求除n!中因子k的个数

int count(int n,int k)
{
    int num=0;
    while(n){
        num+=n/k;
        n/=k;
    }
    return num;
}