整除问题,给定n和a,求最大的k,使n!可被a^k整除但不能被a^(k+1)整除

首先,这道题不可能直接算n!和a^k而后暴力解法,数太大了。那就乖乖找规律吧。
以输入n=6,a = 10,为例。
6! = 2 × 2 × 2 × 2 × 3 × 3 × 5 2\times2\times2\times2\times3\times3\times5 ,
10 = 2 × 5 2\times5 ,
若是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 ;
10 = 2 × 5 2\times5 ;
看到10!和素因数有2,3,5,7,是包含10的全部素因数2和5的,故能够整除,在2和5中,素因数2的个数为8个,素因数5的个数为2个,故k = 2。
晚上迷迷糊糊敲的,好多其实没必要要,懒得改了html

#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;
}