【数学】第十三届蓝桥杯省赛C++ A组/研究生组 Python A组/研究生组《数的拆分》(C++)

【题目描述】

给定 T 个正整数 A_{i},分别问每个 A_{i} 能否表示为 x_{1}^{y1} \cdot x_{2}^{y2} 的形式,其中 x_{1},x_{2} 为正整数,y_{1}, y_{2}为大于等于 2 的正整数。

【输入格式】

输入第一行包含一个整数 T 表示询问次数。

接下来 T 行,每行包含一个正整数A_{i}

【输出格式】

对于每次询问, 如果 A_{i} 能够表示为题目描述的形式则输出 yes,否则输出 no

【数据范围】

对于 10% 的评测用例,1 ≤ T ≤ 200,A_{i} ≤ 10^{9}
对于 30% 的评测用例,1 ≤ T ≤ 300,A_{i} ≤ 10^{18}
对于 60% 的评测用例,1 ≤ T ≤ 10000,A_{i}≤ 10^{18}
对于所有评测用例,1 ≤ T ≤ 100000,1 ≤ A_{i} ≤ 10^{18}

【输入样例】

7
2
6
12
4
8
24
72

【输出样例】

no
no
no
yes
yes
no
yes

【样例解释】

【思路】

题解来源:AcWing 4650. 数的拆分 - AcWing

【代码】

#include <bits/stdc++.h>
typedef long long LL;
const int N = 4010;
int v[N]; // v[i]记录数字i的最小质因子
int prime[N], m;
void init() //线性筛
{
    memset(v, 0, sizeof v); // v[i]记录数字i的最小质因子
    m = 0;                  // m记录质数个数
    for (int i = 2; i <= 4000; ++i)
    {
        if (v[i] == 0) // i是质数
        {
            v[i] = i;
            prime[++m] = i;
        }
        for (int j = 1; j <= m; ++j)
        {
            //若i有比prime[j]更小的质因子,或超出n的范围,则停止循环
            if (prime[j] > v[i] || prime[j] > 4000 / i)
                break;
            // prime[j]是合数i*prime[j]的最小质因子
            v[i * prime[j]] = prime[j];
        }
    }
}
bool check(LL x) //判断一个数是否是平方数或立方数
{
    LL l = 1, r = 2e9;
    while (l < r)
    {
        LL mid = l + r >> 1;
        if (mid * mid >= x)
            r = mid;
        else
            l = mid + 1;
    }
    if (l * l == x)
        return true;
    l = 1, r = 2e6;
    while (l < r)
    {
        LL mid = l + r >> 1;
        if (mid * mid * mid >= x)
            r = mid;
        else
            l = mid + 1;
    }
    if (l * l * l == x)
        return true;
    return false;
}
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int T = 1;
    std::cin >> T;
    init();
    while (T--)
    {
        LL x;
        std::cin >> x;
        if (check(x))
        {
            std::cout << "yes" << '\n';
            continue;
        }
        bool impossible = false;
        for (int i = 1; i <= m; ++i)
        {
            if (x % prime[i] == 0)
            {
                int t = 0;
                while (x % prime[i] == 0)
                {
                    ++t;
                    x /= prime[i];
                }
                if (t == 1)
                {
                    impossible = true;
                    break;
                }
            }
        }
        if (!impossible && check(x))
            std::cout << "yes" << '\n';
        else
            std::cout << "no" << '\n';
    }
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北洋的霞洛

觉得不确可以给个鼓励小费

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值