给定n,a求最大的k,使n!可以被a^k整除但不能被a^(k+1)整除。
https://blog.csdn.net/csyifanZhang/article/details/105754286
↑更好的阅读体验


首先阶乘范围太大,不能直接longlong。所以我们要找到整除的真正含义:


首先,对于一个很大的数a,我们不能直接存储它的值,但是我们可以把它表示成质因数的积,于是第一步我们把a先转化成质因数

核心代码只有几行,从小素数到大素数找起,一旦遇到一个素数因子就不断的将其从a中除掉。有了a的素数因子积的形式,,那么给a取k次方就变成了

map<int, int> m, ma;
for (int i = 0; i < cnt&&primes[i] <= a; i++) {
    while (a%primes[i] == 0) {
        ma[primes[i]]++; a /= primes[i];
    }
}

此时如果我们能把n分解成,那么整除就代表了a的所有素数因子n都有,而且在n中的因此的次幂必然比a中的次幂高,那么我们必须先将阶乘转化为质因数的组合

阶乘的分解与普通数字的分解不同,如果我们想知道中有多少5的因子,那么我们从20开始

显然有4个带5的因子,因此答案为4,我们只需要进行的运算就可以简单的算出他有几个带5的因子。但是我们显然有,这些数字又应该如何进行统计?注意到,如果我们使用进行统计,那么25得到的结果只能是5,但是
$$
所以对于所有25的倍数,我们==需要再进行一次统计==,当然对于所有125的倍数,我们又要==多进行一次统计==,总结一下就是

注意这是一个逐渐推进的过程,对所有5的倍数统计一次,对所有25的倍数统计一次,以此类推。

完结撒花

        map<int, int> m, ma;
        //n!的质因子分解
        for (int i = 0; i < cnt && primes[i] <= n; i++) {
            ll t = n, base = primes[i];
            while (t / base > 0) {
                m[primes[i]] += t / base;
                base *= primes[i];
            }
        }

最后求出最大的k,使得可以被整除,不能被整除,既然整除关系已经转化为了因此的幂次之间的关系,对于a的某个因子他的次数是x,他在n中的幂次假设为y,那么最多取y/x次方之后a的该因子就不小于n中该因子的次数了,即幂次再大就不能整除了。

        ll res = inf;
        for (map<int, int>::iterator i = ma.begin(); i != ma.end(); i++) {
            ll num = (*i).first, cnt = (*i).second;//a的第i个质因子的值和因子数目
            if (cnt > m[num]) { res = 0; break; }
            //k次方就是给每个因子数目cnt×k。
            //要保证整除,a^k的因子num数目最大等于m[num]
            //因此其最多增加 k<=m[num]/k
            res = min(m[num] / cnt, res);
        }

ll isPrime[MAX], primes[MAX], cnt;

int main() {
    ll n, a;
    fill(isPrime, isPrime + MAX, 1);
    //埃及筛法:筛取1-1000所有素数
    for (int i = 2; i < MAX; i++) {
        if (isPrime[i])
            for (int j = i * 2; j < MAX; j += i)
                isPrime[j] = 0;
    }
    for (int i = 2; i < MAX; i++)if (isPrime[i])primes[cnt++] = i;
    while (cin >> n >> a) {
        map<int, int> m, ma;
        //n!的质因子分解
        for (int i = 0; i < cnt && primes[i] <= n; i++) {
            ll t = n, base = primes[i];
            while (t / base > 0) {
                m[primes[i]] += t / base;
                base *= primes[i];
            }
        }

        //a的质因子分解与阶乘不同,每次找到一个因子就把他除掉
        for (int i = 0; i < cnt&&primes[i] <= a; i++) {
            while (a%primes[i] == 0) {
                ma[primes[i]]++; a /= primes[i];
            }
        }
        ll res = inf;
        for (map<int, int>::iterator i = ma.begin(); i != ma.end(); i++) {
            ll num = (*i).first, cnt = (*i).second;//a的第i个质因子的值和因子数目
            if (cnt > m[num]) { res = 0; break; }
            //k次方就是给每个因子数目cnt×k。
            //要保证整除,a^k的因子num数目最大等于m[num]
            //因此其最多增加 k<=m[num]/k
            res = min(m[num] / cnt, res);
        }
        cout << res << endl;
    }
}