题目链接: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=e1p1∗e2p2∗e2p2∗e2p2∗...ekpk
那么
如
果
p
i
%
3
=
=
0
那
么
A
∗
=
e
i
∗
(
p
i
/
3
)
如果pi\%3==0那么A*=e_i*(pi/3)
如果pi%3==0那么A∗=ei∗(pi/3)
现在我们就是要
枚
举
e
i
来
得
到
A
枚举ei来得到A
枚举ei来得到A
我们发现
e
i
的
最
大
值
为
N
1
/
3
e_i的最大值为N^{1/3}
ei的最大值为N1/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/3里的素数那么复杂度是O(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,那么我们把N在N1/4里的素数全部筛出后得到X
那
么
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
那么X的形式为ep∗B,并且e,B>N1/4,那么可以知道:p<4。如果p>=4那么ep∗B>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=3那么B一定等于1证明N3/4∗B,而且B>N1/4那么N3/4∗B>N不可能,所以B=12:p<3那么ei对结果没有贡献
所
以
我
们
枚
举
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;
}