在 10^6 中,有多少个数字以 n 作为它们的最小质因数?

问题描述

for _ in range(int(input())):
    n=int(input())
    least_prime = [0] * (1000001)
    count=0
    for i in range(2,int(1000001**0.5 + 1)): 
 
        if least_prime[i] == 0:
            least_prime[i] = i 

            for j in range(i * i,1000000,2*i) : 
                if (least_prime[j] == 0) : 
                    least_prime[j] = i 
    
    for i in range(2,1000001) : 
        if least_prime[i] == n:
            count+=1
    print(count)

谁能降低问题的时间复杂度?也许尝试了一个小时,但不能比这更简单。 第一个 for loop 是测试用例的数量问题是关于 n 内有多少个数字将 10^6 作为它们的最小素因数?

解决方法

您的代码有 3 个问题:

  • 不管你有多少测试用例,你都重复同样的任务,这是浪费时间和资源
  • 保持不变/忽略 web.xml 上方的数字/质数
  • 并且通过在您的 j 范围内执行 2*i 的步骤,您错误地标记了一堆数字,例如 6,它应该将 2 标记为它的最小素数,但它被标记为它自己,因为它被跳过了,6= 4+2 但你永远不会用你的 j 范围到达那里,因为你一步 4 所以你走 4,8,12,... 而不是 4,6,...

如何解决?简单,先做一次筛子,不需要重复完全相同的事情 10**6 次,或者不管你有多少测试用例,两次或两次以上是两次太多次(如果 n 总是质数,即 78498,这是小于 int(1000001**0.5 + 1)) 的素数个数,其他 2 个点简单修复

我会把它放在它自己的函数中,这使得它更可重用且易于使用,对于计数部分,你怎么做是没有问题的,但使用Counter更方便一次完成所有计数

10**6

所以现在你的测试可以很简单

from collections import Counter

def make_sieve(MAX):
    MAX += 1
    least_prime = [0] * MAX
    for i in range(2,MAX): 
        if least_prime[i] == 0:
            least_prime[i] = i 
            for j in range(i * i,MAX,i) : 
                if (least_prime[j] == 0) : 
                    least_prime[j] = i
    return least_prime

result = Counter(make_sieve(10**6))

print("n=2->",result[2])# n=2-> 500000
print("n=3->",result[3])# n=3-> 166667

为了完整起见,这里是没有计数器的方法

for _ in range(int(input())):
    n = int(input())
    print(result[n])

但这也太长了,一个列表已经为我们做了 least_prime = make_sieve(10**6) for _ in range(int(input())): n = int(input()) count = 0 for p in least_prime: if p==n: count+=1 print(count)

.count

计数器仍然更好,因为只需一次你就可以得到所有的答案,如果需要,你可以用一本普通的字典制作自己的答案,但我把它留给读者作为练习。