简体   繁体   中英

How many numbers have n as their smallest prime factor within 10^6?

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)

Can anyone reduce the time complexity of the problem? tried for an hour maybe but can't simplify more than this. First for loop is for the number of test cases. And the question is regarding how many numbers have n as their smallest prime factor within 10^6 ?

there are 3 problems with your code:

  • you repeat the same task however many test case you have, which is a waste of time and resources
  • you leave unchanged/ignore the numbers/primes above int(1000001**0.5 + 1)
  • and by doing a step of 2*i in your j range you mislabel a bunch of number, like for example 6, which should have 2 marked as its least prime but it get marked as itself because it get skipped, 6=4+2 but you never get there with your j range because you make a step of 4 so you go 4,8,12,... instead of 4,6,8,...

How to fix it? simple, make the sieve first and only once, no need to repeat the exact same thing 10**6 times or however many test case you have, two or more is two too many times ( if n is always prime that is 78498 which is the number of primes less than 10**6 ), and the other 2 points are simple fix

I would put it inside its own function, which make it more reusable and easy to play with, and for the counting part, there is no problem with how you do it, but is more convenient with a Counter which make all the counting at once

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

so now your test can be as simple as

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

And just for completeness, here is how you can do it without the Counter

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)

but that is also too long, a list already do that for us with .count

least_prime = make_sieve(10**6)
for _ in range(int(input())):
    n = int(input())
    count = least_prime.count(n)
    print(count)

The counter is still better, because in just one go you get all the answers, and if needed you can make your own with a regular dictionary, but I leave that as exercise to the reader.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM