2020牛客寒假算法基础集训营6 E-立方数 - 质因子分解

题目链接:https://ac.nowcoder.com/acm/contest/3007/E
题目大意:
在这里插入图片描述
在这里插入图片描述
我们要求最大的A。
我们根据唯一分解定理:
N = e 1 p 1 ∗ e 2 p 2 ∗ e 2 p 2 ∗ e 2 p 2 ∗ . . . e k p k N=e_1^{p_1}*e_2^{p_2}*e_2^{p_2}*e_2^{p_2}*...e_k^{p_k} N=e1p1e2p2e2p2e2p2...ekpk
那么
如 果 p i % 3 = = 0 那 么 A ∗ = e i ∗ ( p i / 3 ) 如果pi\%3==0那么A*=e_i*(pi/3) pi%3==0A=ei(pi/3)
现在我们就是要 枚 举 e i 来 得 到 A 枚举ei来得到A eiA
我们发现 e i 的 最 大 值 为 N 1 / 3 e_i的最大值为N^{1/3} eiN1/3
我们枚举 N 1 / 3 里 的 素 数 那 么 复 杂 度 是 O ( T N ( 1 / 3 ) / l n ( N ( 1 / 3 ) ) ) N^{1/3}里的素数那么复杂度是O(TN^{(1/3)}/ln(N^{(1/3)})) N1/3O(TN(1/3)/ln(N(1/3)))
我们可以进一步优化: 如 果 枚 举 到 N 1 / 4 , 那 么 我 们 把 N 在 N 1 / 4 里 的 素 数 全 部 筛 出 后 得 到 X 如果枚举到N^{1/4},那么我们把N在N^{1/4}里的素数全部筛出后得到X N1/4,NN1/4X
那 么 X 的 形 式 为 e p ∗ B , 并 且 e , B > N 1 / 4 , 那 么 可 以 知 道 : p < 4 。 如 果 p > = 4 那 么 e p ∗ B > N 那么X的形式为e^{p}*B,并且e, B>N^{1/4},那么可以知道:p<4。如果p>=4那么e^{p}*B>N XepB,e,B>N1/4p<4p>=4epB>N
1 : p = 3 那 么 B 一 定 等 于 1 证 明 N 3 / 4 ∗ B , 而 且 B > N 1 / 4 那 么 N 3 / 4 ∗ B > N 不 可 能 , 所 以 B = 1 2 : p < 3 那 么 e i 对 结 果 没 有 贡 献 \begin{array}{l} 1:p=3那么B一定等于1 证明N^{3/4}*B,而且B>N^{1/4}那么N^{3/4}*B>N不可能,所以B=1 \\ \\ 2:p<3那么ei对结果没有贡献 \\ \end{array} 1:p=3B1N3/4B,B>N1/4N3/4B>N,B=12:p<3ei
所 以 我 们 枚 举 N 1 / 4 的 素 数 , 再 判 断 X 是 否 为 立 方 数 , 复 杂 度 : O ( T N ( 1 / 4 ) / l n ( N ( 1 / 4 ) ) ) 所以我们枚举N^{1/4}的素数,再判断X是否为立方数,复杂度:O(TN^{(1/4)}/ln(N^{(1/4)})) N1/4,X:O(TN(1/4)/ln(N(1/4)))

#include<bits/stdc++.h>
#define LL long long
using namespace std;
 
#define MAXN 1000005
#define MAXL 5299710
LL prime[MAXN];
LL Lf[MAXN];//存储立方
LL check[MAXL];
LL tot = 0;
void get_prime(LL n){
    memset(check, 0, sizeof(check));
    for(LL i = 2; i <= n; ++i){
      if (!check[i])
        prime[tot++] = i, Lf[tot-1]=i*i*i;
 
      for (LL j = 0; j < tot; ++j){
        if (i * prime[j] > n)
          break;
 
        check[i*prime[j]] = 1;
        if (i % prime[j] == 0)
          break;
      }
    }
}
 
int main(){
 
    get_prime(31622);
    int t;scanf("%d", &t);
    while(t--){
        LL n, A=1;scanf("%lld", &n);
        for(int i=0; i<tot&&prime[i]<=n; i++){
            while(n%Lf[i]==0){//立方筛完
                A*=prime[i];
                n/=Lf[i];
            }
            while(n%prime[i]==0){
                n/=prime[i];
            }
        }
 
        int lb = 1, rb = 1000000;//二分判断X是不是立方数
        while(lb <= rb){
            int md = lb + rb >> 1;
            if((LL)md * md * md < n)
                lb = md + 1;
            else
                rb = md - 1;
        }
        if((LL)lb * lb * lb == n)
            A *= lb;
        printf("%lld\n", A);
    }
 
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值