CCF-CSP 202312-2 因子化简(Python)

因子化简(Python)

本题解参考自:CCF-CSP 202312-2 因子化简(Java、C++、Python)_因子化简问题-CSDN博客

一、前置知识(质数筛选)

  1. 质数就是除了1和它本身没有其他因数的数。根据定义,判断一个数n是不是质数,我们要遍历[2,n-1],如果它不能被这些数中的任何一个整除,那它就是一个质数。这样做的时间复杂度是O(n),我们要筛n-2个数,才能确定一个数是质数。有没有方法优化它呢?有。根据数学定义,我们可以把遍历的范围从[2,n-1]缩小到[2,\sqrt{n-1}],这样,时间复杂度就变成O(\sqrt{n})。这个是比较常见的思路。

  2. 上面的方法是比较常见的,即给定一个数,让你求这个数是不是质数。但如果给定一个数,让你求从1到这个数的所有自然数是不是质数呢?(问题1)这个时候时间复杂度就很大了。我们需要继续缩小筛选范围,让需要筛查的数字变少,这样时间复杂度就降下来了。怎么做呢?我们其实可以只筛查[2,\sqrt{n-1}]的所有质数(因为你在求解问题1的时候,肯定是从小到大找质数的,那比你当前正在检测的这个数小的哪些质数就都已经被找出了,可以利用)。这个结论的原理在此不作证明。这个其实就是埃式筛。

  3. 还有一种方法叫线性筛。道理其实也一样,就是让需要筛查的数变少,这样时间复杂度就降下来了。说到底就是数学前置知识,知道了就好,算法就更快。

以上参考自:算法篇——素数筛-CSDN博客

二、问题

链接:计算机软件能力认证考试系统

三、分析

第一步,根据问题,我们要做一张质数表。所以我们要利用前置知识的第二点。题目给的数字范围是在[1,1的10次方]。质数最大也就是[1,1的5次方],我们只要做出这个范围内的质数表。

max_val = 100000
primes = [] #质数表
for i in range(2,max_val):
    #判断当前数是不是质数
    if all(i%p!=0 for p in primes if p*p<=i): 
        primes.append(i)

第二步,分解质因数。我们设立一个长度为max_val的空列表cnt,索引代表质因数,值代表质因数的次数。题目还要求我们如果找不到质因数,就默认答案是1,针对这一点,我们可以设立变量ans,初始时ans=n(n即给出的要分解的数)。原来的数n会被不断地除,直到等于1。我们在除完n之后,设置ans // = n。此时,如果一开始的n不能被分解,那么n就是还是n,ans //= n后ans会变成1,就可以满足题目的要求了。

四、完整代码

def factorSimpliying(q,Q,primes):
    max_val=100000
    for i in range(q):
        n,k=Q[i][0],Q[i][1]
        ans=n
        cnt=[0] * max_val
        for prime in primes:
            while n % prime == 0:
                n //= prime
                cnt[prime] +=1
​
        ans //= n
        for prime,t in enumerate(cnt):
            if t<k and t!=0:
                ans //= pow(prime,t)
​
        print(ans)
​
#1 输入
q = int(input())
Q = [list(map(int, input().split())) for _ in range(q)]
# 找质数
max_val=100000 #因为最大的数是10的10此方,所以它的质数最大是10的5次方
primes = []
for i in range(2,max_val):
    #判断当前i是不是质数
    if all(i%p!=0 for p in primes if p * p <= i):
        primes.append(i)
​
#2 输出
factorSimpliying(q,Q,primes)

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值