立方数

立方数

题目描述

对于给定的正整数 $N$,求最大的正整数 $A$,使得存在正整数 $B$,满足 $A^3B=N$。

输入包含 $T$ 组数据,$1 \leq T \leq 10000$;$1 \leq N \leq 10^{18}$。

输入描述:

第一行数字 $T$ 表示数据组数。

接下来一行,$T$ 个正整数 $N$。

输出描述:

$T$ 行,每行一个数字表示答案。

示例1

输入

4
27 24 7 54

输出

3
2
1
3

 

解题思路

  感觉这题的正解挺难想到的,也很难解释为什么会这么想,我尽量构造一下其中的逻辑链。

  将 $N$ 分解成质因子乘积的形式 $N = P_1^{\alpha_1} P_2^{\alpha_2} \cdots P_m^{\alpha_m}$,那么最大 $A$ 就是 $P_1^{\left\lfloor \alpha_1/3 \right\rfloor} P_2^{\left\lfloor \alpha_2/3 \right\rfloor} \cdots P_m^{\left\lfloor \alpha_m/3 \right\rfloor}$。因此只有幂次至少为 $3$ 的质因子才对 $A$ 有贡献。但问题在于,我们得先知道 $N$ 的质因子分解,才能计算出这些幂次,而要枚举 $N$ 以内的质数显然不可行。

  我们可以先从枚举约数的方法开始,把 $A^3 B = N$ 中的 $A^3$ 与 $B$ 看作是 $N$ 的约数。我们可以枚举 $N$ 的所有约数 $d$,如果 $\sqrt[3]{d}$ 是整数,则说明存在一个满足条件的 $A = \sqrt[3]{d}$。我们只需要找到所有约数中 $\sqrt[3]{d}$ 为整数的最大那个 $d$,其对应的 $\sqrt[3]{d}$ 就是最大的 $A$。但朴素枚举 $N$ 的所有约数的复杂度为 $O\left( \sqrt{N} \right)$,会超时。

  接着再想办法优化,注意到 $A^3 B = N \Rightarrow A = \sqrt[3]{N/B} \leq \sqrt[3]{10^{18}/1} = 10^6$,这说明我们其实只需要考虑 $10^6$ 以内的质因子,因为如果某个质因子大于 $10^6$,其 $3$ 次幂就会超过 $10^{18}$,与 $N \leq 10^{18}$ 矛盾。所以我们可以先筛出 $10^6$ 以内的所有质数(一共 $78498$ 个质数),然后依次枚举这些质数来试除 $N$,求出每个质因子的幂次,再套用最开始提到的公式计算出最大 $A$。然而处理单个 $N$ 的复杂度为 $\pi\left(\sqrt[3]{N}\right)$,所有询问的总复杂度为 $T \cdot \pi\left(\sqrt[3]{N}\right)$,还是会超时。

  实际上做到这里我也很难再想到更优的解法了,无奈下只能查看题解,结果发现只需考虑 $\sqrt[4]{N}$ 内的质因子就行。这个步骤的跳跃性很大,难以解释为什么。不过我们还是可以硬推一下其背后的逻辑。首先尝试 $\sqrt{N}$ 内的约数,发现不行再考虑 $\sqrt[3]{N}$ 内的质因子,还不行再试试 $\sqrt[4]{N}$ 的质因子。下面来分析一下为什么只需考虑 $\sqrt[4]{N}$ 的质因子。

  我们先枚举 $\sqrt[4]{N}$ 以内的质因子并试除 $N$,剩下的部分记为 $N'$,将其分解成 $N' = P_1^{\alpha_1} P_2^{\alpha_2} \cdots P_m^{\alpha_m}$,其中每个质因子都大于 $\sqrt[4]{N}$ 的,即 $P_i > \sqrt[4]{N}$。此时可以分两种情况讨论:

  • 如果 $m=1$,即 $N' = P_1^{\alpha_1}$ 只有一个质因子,那么一定有 $\alpha_1 \leq 3$。否则如果 $\alpha_1 \geq 4$ 则 $P_1^{\alpha_1} > \left(\sqrt[4]{N}\right)^4 > N$,矛盾。
  • 如果 $m > 1$,则每个 $\alpha_i < 3$。比如某个 $\alpha_i \geq 3$,有 $P_i^{\alpha_i} P_j^{\alpha_j} > \left(\sqrt[4]{N}\right)^3 \times \sqrt[4]{N} = N$,矛盾。

  此时,我们只需 $O(1)$ 判断 $\sqrt[3]{N'}$ 是否为整数,就可以确定 $N'$ 是否存在幂次为 $3$ 的唯一质因子。最终总的复杂度为 $T \cdot \pi\left(\sqrt[4]{N}\right)$,可以通过。

  AC 代码如下,时间复杂度为 $O\left(T \cdot \pi\left(\sqrt[4]{N}\right)\right)$:

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

typedef long long LL;

const int N = 32005;

int prime[N], cnt;
bool vis[N];

void init() {
    for (int i = 2; i < N; i++) {
        if (!vis[i]) prime[cnt++] = i;
        for (int j = 0; prime[j] * i < N; j++) {
            vis[prime[j] * i] = true;
            if (i % prime[j] == 0) break;
        }
    }
}

void solve() {
    LL n;
    cin >> n;
    LL ret = 1;
    for (int i = 0; i < cnt; i++) {
        int p = prime[i], c = 0;
        while (n % p == 0) {
            c++;
            n /= p;
        }
        c /= 3;
        while (c--) {
            ret *= p;
        }
    }
    LL t = cbrtl(n);
    if (t * t * t == n) ret *= t;
    cout << ret << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    init();
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  【题解】2020牛客寒假算法基础集训营第六场:https://ac.nowcoder.com/discuss/367149

posted @ 2025-11-21 23:24  onlyblues  阅读(3)  评论(0)    收藏  举报
Web Analytics