P4446 [AHOI2018初中组] 根式化简

题目链接

算法

素数筛。

思路

有一个结论,如果将一个数 \(x\)\(x^{\frac{1}{4}}\) 内的素因子筛掉,那么剩下的数一定是一个完全立方数或者不能被开立方。

如何证明呢?

采用反证法,若存在因子 \(p > x^{\frac{1}{4}}\),使得剩下的 \(x\) 能被表示为 \(p^3 \times a\),那 \(a\) 一定大于 \(x^{\frac{1}{4}}\)(因为之前已将 \(\le x^{\frac{1}{4}}\) 的因子筛完了),所以 \(p^3 \times a > x\),与命题矛盾,得证。

接下来考虑实现。

因为 \(\sqrt[4]{10^{18}} < 32000\),所以我们可以先预处理出 32000 内的素数。

再将 \(\le x^{\frac{1}{4}}\) 的素因子筛去,如果有 3 次方的记得加在答案里。

最后处理完,判断剩下的 \(x\) 是否是完全立方数即可(可以预处理一个 \(x^{\frac{1}{3}}\) 的数组,最后进行二分查找)。


#include "iostream"

#include "cmath"

using namespace std;

#define int long long

const int N = 3.2e4 + 1;

int prime[N], cnt = 0;
bool is_prime[N];

inline void init_prime() {
    for (int i = 2; i <= 3.2e4; ++i) {
        if (!is_prime[i])
            prime[++cnt] = i;
        for (int j = 1; j <= cnt and i * prime[j] <= 3.2e4; ++j) {
            is_prime[i * prime[j]] = 1;
            if (!(i % prime[j]))
                break;
        }
    }
    return;
}

inline void calculate(int x) {
    int t = sqrt(sqrt(x)), ans = 1;
    for (int i = 1; i <= cnt and prime[i] <= t; ++i) {
        int tot = 0;
        while (!(x % prime[i])) {
            x /= prime[i], ++tot;
            if (tot == 3)
                ans *= prime[i], tot = 0;
        }
    }

    int f = round(pow(x, 1.0 / 3));
    if (f * f * f == x)
        ans *= f;
    cout << ans << '\n';
    return;
}

int n;

inline void solve() {
    init_prime();
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        calculate(x);
    }
    return;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    solve();
    return 0;
}

posted @   Steven1013  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示