本文综合了上面的官网里的其他用户的题解及代码,并加入自己的理解
1. 题解
1.1 分析有几种情况符合题目要求
由唯一分解定理,任何大于1的整数a都可以分解为它的质因数的乘积
其中p_i是a_i的质因数,k_i是大于等于1的整数
有如下几种形式:(形式1)
;(形式2)
;(形式3)
(显然可以归到
的形式);(形式4)
(就是将唯一分解中,指数为偶数的部分化为
放入
那一堆,指数为奇数的部分化为
分别放
那堆和
那堆)
1.2 如何检查一个数a是否符合上面的任一形式
观察形式1,2,4,可知,只要a唯一分解后得到的质因数的指数大于或等于2,这个质因数就能对应到某种形式;只要所有质因数都能对应到某种形式,a就是符合要求的。
一般的唯一分解算法需要求n以内的素数,复杂度
,复杂度高达10^9,超时
逐一分析上面的每种形式。
形式1:特判
是否为整数
形式2:特判
是否为整数
形式4:?
1.3 形式4
考虑
,以
为分界点,分类讨论
case 1:
case 2:
则case 1可以转化为
case 2可以转为
a'相当于缩小了问题规模,因为它的
、
都小于
,要检查它是否符合我们之前提到的形式4,作唯一分解,只需要
以内的素数(因为我们限定了
、
的大小!),复杂度
,令
,
约为4000,
约为64,配合T的上界10^5,刚好在10^7!
至于case 1、2括号后面的部分,因为不知道
、
的大小是否落在
内,可能唯一分解不到。我们对a做完
以内的素数唯一分解后,若a剩余的部分大于1,说明
、
落在
外,那我们就需要额外判断a剩余部分开二次根号(对应
)或开立方根(对应
)是否为整数。
2. AC代码
顺便说一句,python代码作素数唯一分解的时候,除法必须用“//”而不是“/”,不然答案是错的。我想破脑袋也不明白为什么,如有读者知道,麻烦在评论留下你的见解。
# 参考蓝桥杯官网题解“python战狼”的代码,感谢
MAXN=4000
primes=[]
# 欧拉筛O(n)
def pre():
global primes,MAXN
not_prime = [False for _ in range(MAXN)]
for i in range(2,MAXN):
if not not_prime[i]:
primes.append(i)
for p in primes:
if i*p>=MAXN:
break
not_prime[i * p] = True
if i%p==0:
'''
i是p的倍数,之前已被p筛过;又素数表中素数从小到大
排列,此后i*p'必为p的倍数,此后仍会被p筛一次,不需要
在这里先筛一次
'''
break
def is_square(x):
temp = int(x**(1 / 2))
return temp ** 2 == x or (temp + 1) ** 2 ==x # 小心误差!
def is_cubic(x):
temp = int(x**(1 / 3))
return temp ** 3 == x or (temp + 1) ** 3 == x # 小心误差!
def judge(a):
global primes
if a == 1:
return False
# a是否为某个数的平方
if is_square(a):
return True
# a是否为某个数的3次方
if is_cubic(a):
return True
# a是否为某个数的4次方
# 已包括在平方的判断内
# a是否为(x1^2)*(x2^3)的形式
for p in primes:
if a < p:
break
cnt = 0
while a % p == 0:
a //= p # 为什么用/就会错啊啊啊!!!!!!!!!!!!!!!!!!
cnt += 1
if cnt == 1:
return False
if a != 1:
if not is_square(a) and not is_cubic(a):
return False
return True
t=int(input())
pre()
for i in range(t):
a=int(input())
if judge(a):
print("yes")
else:
print("no")