题目:

细胞分裂

题目解析

先看题目,肥肠的长,但是我们简化后就是设xx是最小的使得m1m2Sixi{m_{1}}^{m_{2}}\vert {S{i}}^{x_{i}}的整数(也有可能不存在),求min(x1,...,xn)\min(x_1, ...,x_n)

虽说关键数字m1m2{m_{1}}^{m_{2}}大的吓人但是你先别急

先介绍一个


推论

给定a=p1a1p2a2...psasa = {{p_1}^{a_1}{p_2}^{a_2}...{p_s}^{a_s}},而 ddaa 的约数的充要条件是d=p1a1p2a2...psasd = {{p_1}^{a_1}{p_2}^{a_2}...{p_s}^{a_s}}0ejaj0 \leq e_j \leq a_j1js1 \leq j \leq s,即 dd 中每一个质数的幂次都不超过 aa 的。
因此,每个质因子上的幂次直接决定了两数之间的整除性。
例如 12=22×312 = 2^2 \times 372=23×3272 = 2^3 \times 3^2, 看到 1212 的质因子上的幂次都对应的比 7272 小, 便可以在进行取模运算的情况下给出 127212 \vert 72 的结论


有了推论的铺垫,这道题的突破口也是很明显的:
如果m1=p1a1p2a2...psasm_1 = {{p_1}^{a_1}{p_2}^{a_2}...{p_s}^{a_s}}, 那么m1m2=p1a1m2p2a2m2...psasm2{m_1}^{m_2} = {{p_1}^{a_1m_2}{p_2}^{a_2m_2}...{p_s}^{a_sm_2}}。接下来只需要解决题意中的 xix_i 的求解。
由推论可以得到, 若m1m2{m_1}^{m2}中的每个质因子的幂次都比S1xi{S_{1}}^{x_i} 小时,m1m2S1xi{m_1}^{m2}\vert {S_{1}}^{x_i}成立。S1xi{S_{1}}^{x_i} 中的质因子是否出现由 SiS_i 决定,而质因子出现了几次主要由 xix_i 决定。若 Si=p1e1p2e2...psesps+1es+1...ps+res+rS_i = {{p_1}^{e_1}{p_2}^{e_2}...{p_s}^{e_s}{p_{s+1}}^{e_{s+1}}...{p_{s+r}}^{e_{s+r}}}ps+1es+1{p_{s+1}}^{e_{s+1}}ps+res+r{p_{s+r}}^{e_{s+r}} 表示与 m1m_1 无关的质因子),那么xix_i 应该使得 1js1 \leq j \leq sjj,满足 ajm2ejxia_jm_2 \leq e_jx_i
所以从 m1m_1中的每个质因子 pjp_j 出发: 如果这个SiS_i 不能整除 pjp_j,则说明 SiS_i 不包含 pjp_j 这个质因子,进而找不到题设所要求的xix_i;如果这个SiS_i 能整除 pjp_j,那么只需要求出对应的eje_j,就能算出第 jj个质因子, 要求 xix_i 不小于 ajm2ej\lceil \frac {a_jm_2}{e_j} \rceil,在对所有的这样的要求取最大值,就都得到了 xix_i。最后对所有合法的 xix_i 取最小值就是答案

代码

#include <bits/stdc++.h>
using namespace std;

unordered_map<int, int> pri; // 记录对应质数出现的次数
int m1, m2, n, ans = 2147483647, x;

void fenjie (int a) {
    for (int i = 2; i <= sqrt(a); i++) {
        if(a % i == 0) {
            pri[i]++;
            a /= i;
            i--;
        }
    }
    if(a > 1) {
        pri[a]++;
    }
}

int main() {
    cin >> n >> m1 >> m2;
    fenjie(m1);
    while(n--) {
        cin >> x;
        int res = 0;
        for (pair<int, int> p : pri) {
            int t = p.first;
            if(x % t != 0) { // 说明这个数没有 t 这个质因子,不符合要求
                res = -1;
                break;
            } else {
                int cnt = 0;
                for(; x % t == 0; x /= t) {
                    cnt++; // 统计这个质因子出现了几次
                }
                res = max(res, (int)ceil(m2 * 1.0 * p.second / cnt));
            }
        }
        if(res >= 0) {
            ans = min(ans, res);
        }
    }
    if (ans >= 2147483647) {
        cout << -1 << endl;
    } else {
        cout << ans << endl;
    }
    return 0;
}