题目名称:寻因找祖
时间限制:1000ms内存限制:256M
题目描述
寻找因子个数为n的最小整数x.
输入描述:
输入整数n。(1<=n<=1000)
输出描述:
输出x。
示例
示例1
输入
3
输出
4
提示
无
猛一看,这个题目很简单啊,先不考虑复杂度问题,我们直接暴力来一次,很简单的
直接对一个较大数进行循环,判断到底有多少因子,因子数量与输入的数一致就输出这个数
于是,很简单的就得到一个暴力傻瓜的代码
class Solution:
def __init__(self) -> None:
pass
def solution(self, n):
result = None
# TODO: 请在此编写代码
if n<3:
return n
for i in range(1000):
z = [1,i] # 把1和数本身
for j in range(2,n):
if i%j==0:
z.append(j)
if len(z)==n:
#z.sort()
#print(z) # 查看因子组合都有哪些数
return i
return result
if __name__ == "__main__":
n = int(input().strip())
sol = Solution()
result = sol.solution(n)
print(result)
很轻松就得到了 70% 的通过率,很简单嘛
然后,考虑到部分数字只能是2^n,这里的n一定是素数
那么,再追加一个素数判断
# TODO: 请在此编写代码
if n<3:
return n
su = [2,3,5,7,11,13,17,19]
for i in range(21,n+1,2):
isSu = True
for j in su:
if i % j == 0:
isSu = False
break
if isSu:
su.append(i)
if n in su:
return 2 ** (n-1)
for i in range(1000):
z = [1,i] # 把1和数本身
for j in range(2,n):
if i%j==0:
z.append(j)
if len(z)==n:
#z.sort()
#print(z) # 查看因子组合都有哪些数
return i
return result
哦吼,直接飙到 90% 的通过率了,那么问题来了,以上这些都是没有考虑到大数因子的情况,比如输入值是1000怎么搞,这个肯定算不出来的,而且,每日一练的提交用例测试里,还真有一个1000作为测试数据的。。。
为了 100% 通过率,老顾开始上头,先百度别人的解决办法,找到一个好文章
https://blog.csdn.net/weixin_73178250/article/details/126790315
。。。。。。嗯,抄这个代码,直接是 100% 通过率,问题是,你这个公式是什么鬼?你这个实现和这个公式有什么关系?老顾不造啊,老顾蒙圈啦,老顾自闭咯。。。。。。。
还是让老顾死一死去冷静一下。。。。。
抽完烟回来,不死心,应该不是就这么一个公式可以达到这个题的解答吧,哪怕有点其他笨办法呢?
于是,再次进行搜索,找到另一篇文章
https://blog.csdn.net/Cey_Tao/article/details/126747772
嗯,这个就舒服多了,没有那些难懂的公式,没有那些难懂的实现
这个描述多简单啊,直接就可以理解了,比如,我要找一个12个因子的最小数,那么,先把12分解,成为 [2 , 2 , 3],那么最小12因子的数就可以用这个组合来判断出来了,结合槐阳7的讲解,那么,我们只需要根据这个因子来判断出所有组合,然后根据各个组合计算出最终值,得到最小的就好,至于上边这两个文章里的 dfs 什么的,都见鬼去吧,老顾用个笨办法先实现出来看看
# 请关闭中文输入法,用英文的字母和标点符号。
# 如果你想运行系统测试用例,请点击【执行代码】按钮,如果你想提交作答结果,请点击【提交】按钮,
# 注意:除答案外,请不要打印其他任何多余的字符,以免影响结果验证
# 本OJ系统是基于 OxCoder 技术开发,网址:www.oxcoder.com
# 模版代码提供基本的输入输出框架,可按个人代码习惯修改
class Solution:
def __init__(self) -> None:
pass
def solution(self, n):
result = None
# TODO: 请在此编写代码
# 避免有特例1掉坑
if n<3:
return n # 10% 通过
# 获取当前数字 n 之内的所有素数
su = [2,3,5,7,11,13,17,19]
for i in range(21,n+1,2):
isSu = True
for j in su:
if i % j == 0:
isSu = False
break
if isSu:
su.append(i)
# 如果是素数直接返回
if n in su:
result = 2 ** (n-1) # 30%,与之前的10% 组合成 40%
else:
# (1+a1)(1+a2)(1+a3)...看看公式多简单
t = [] # 得出因子数的各个素数因子
x = n
while x > 1:
for i in su:
if i>x:
break
if x % i ==0:
t.append(i)
x //= i
# 根据各个素数因子的数量得出可以得到多少中组合
# 比如 15 个因子,15 分解成 3 和 5
# 只有两种组合,即 2**4 * 3**2 和 2 ** 14 的组合
# 我们默认非素数时,不返回 2**(n-1),所以就当做只有一种组合
t.sort(reverse=True)
o = [[t.count(k),k] for k in t]
g = 1
for i in o:
g *= i[0]
# 如果只有一种组合,则直接输出
if g==1:
#print(o)
r = 1
for i in range(len(t)):
r *= su[i]**(t[i]-1)
return r # 20% 与之前的 40% 组合成 60%
else:
# 获得所有的组合,然后根据组合分别计算取最小的值即可
z = self.MakeGroup([t])
final = []
mx = 2**(n-1)
for grp in z:
r = 1
for i in range(len(grp)):
r *= su[i]**(grp[i]-1)
if r<mx:
mx = r
final = grp
#print(mx,grp)
result = mx
return result
# 老顾的笨办法,将各种组合枚举出来
# 比如 [3,3,2,2]
# 就可以得到 [[3,3,2,2],[4,3,3],[6,3,2],[9,2,2],[9,4],[12,3],[18,2]]
# 然后便利组合即可
def MakeGroup(self,arr):
l = len(arr[-1])
if l == 2:
arr.append([arr[-1][0]*arr[-1][1]])
else:
same = [i for i in arr if len(i)==l]
for i in range(len(same)):
f = [j for j in same[i]]
c = same[i]
for m in range(l-1):
for n in range(m+1,l):
nn = c[m]*c[n]
nt = c[:m]+c[m+1:n]+c[n+1:]+[nn]
nt.sort(reverse=True)
if nt not in arr:
arr.append(nt)
arr = self.MakeGroup(arr)
return arr
if __name__ == "__main__":
n = int(input().strip())
sol = Solution()
result = sol.solution(n)
print(result)
很好,通过率100%了,复杂度估计除了排列组合哪里,也没什么复杂度了,哦耶,让那个 dfs 见鬼去吧