2020牛客寒假算法基础集训营6.E——立方数【数学 & 二分】(待补)

题目传送门


题目描述

对于给定的正整数 N,求最大的正整数 A,使得存在正整数 B,满足 A3B=N
输入包含 T 组数据, 1 T 10 , 000 1 N 1 0 18 1≤T≤10,000;1≤N≤10^{18}


输入描述:

第一行数字 T 表示数据组数
接下来一行,T 个正整数 N


输出描述:

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


输入

4
27 24 7 54


输出

3
2
1
3


题解

  • 考虑直接一些的做法
  • 尝试对每个N作质因数分解,经简单的统计可得出答案,复杂度 O ( T N 1 / 2 ) O(TN^{1/2})
  • 我们先做简单一点的优化,容易发现其实只要枚举106(N(1/3)以内)的质数就好,复杂度 O ( T N 1 / 3 / l n ( N 1 / 3 ) ) O(TN^{1/3}/ln(N^{1/3}))
  • 再作进一步的分析,如果我们仅使用N^(1/4)(记为W)以内的质数去试除,那么最后余下的数X仅具有大于W的因子
  • 此时X要么是一个完全立方数,要么对答案没有任何贡献,只需要使用二分法来验证X是不是一个完全立方数即可
  • 复杂度 O ( T N 1 / 4 / l n ( N 1 / 4 ) ) O(TN^{1/4}/ln(N^{1/4})) ,不卡常数,真的!

AC-Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <time.h>
 
using namespace std;
typedef long long LL;
const int N = 31700;
 
int is[N], n, pri[N]; LL x, p_tri[N], p_ss[N];
int main()
{
     
    int i, j, k;
    for(i = 2; i < N; i ++){
        if(is[i] == 0){
            pri[++ pri[0]] = i;
            p_tri[pri[0]] = (LL)i * i * i;
            p_ss[pri[0]] = (LL)i * i * i * i;
            for(j = i * i; j < N; j += i)
                is[j] = 1;
        }
    }
    scanf("%d", &n);
    while(n --){
        int ans = 1;
        scanf("%lld", &x);
        for(i = 1; p_ss[i] <= x; i ++){ 
            if(x % pri[i] == 0){
                while(x % p_tri[i] == 0){
                    ans *= pri[i];
                    x /= p_tri[i];
                }
                while(x % pri[i] == 0)
                    x /= pri[i];
            }
        } 
        int lb = 1, rb = 1000000;
        while(lb <= rb){
            int md = lb + rb >> 1;
            if((LL)md * md * md < x)
                lb = md + 1;
            else
                rb = md - 1;
        }
        if((LL)lb * lb * lb == x)
            ans *= lb;
        printf("%d\n", ans);
    }
      
    return 0;
}

发布了203 篇原创文章 · 获赞 130 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Q_1849805767/article/details/104423371