📜  门|门CS 2010 |第 65 题(1)

📅  最后修改于: 2023-12-03 14:58:37.052000             🧑  作者: Mango

题目介绍:门|门CS 2010 |第 65 题

题目描述

给定一个正整数 n,表示有 n 扇门,编号从 1 到 n。现开始遍历这些门,从第一个门开始,每次经过 i(i 为当前所在门的编号)时,就将 i 的倍数的门的状态(开或关)取反。问最后有多少扇门是开着的。

输入格式

一个正整数 n。

输出格式

一个正整数,表示开着的门的数量。

数据范围

1 ≤ n ≤ 10 ^ 7

样例

输入

10

输出

3
题解
思路

这道题我们可以发现,如果一个数有奇数个约数,那么最后它的状态一定是开着的,如果它有偶数个约数,那么最后它的状态一定是关着的。那么对于每一个数,我们都只要求出它有多少个约数就可以知道它最后的状态了。又因为一个数的因数是成对出现的,如果它能被分解成两个不同的质数,那么它必然有偶数个因子,否则它只能被分解成一个数的平方,而它只有一个平方因子,因此只有奇数个因子。所以我们只需要求出每一个数是否能被分解成两个不同的质数就可以知道它最后的状态了。

代码片段
import math

def is_prime(num):
    if num <= 1:
        return False
    for i in range(2, int(math.sqrt(num)) + 1):
        if num % i == 0:
            return False
    return True

def get_divisor_num(num):
    res = 1
    for i in range(2, int(math.sqrt(num)) + 1):
        count = 0
        while num % i == 0:
            count += 1
            num //= i
        if count != 0:
            res *= (count + 1)
    if num != 1:
        res *= 2
    return res

def get_open_door_num(n):
    count = 0
    for i in range(1, n + 1):
        if is_prime(i):
            count += 1
        elif i % 4 == 0:
            count += 1
        elif get_divisor_num(i) % 2 == 1:
            count += 1
    return count

n = int(input())
print(get_open_door_num(n))

时间复杂度: $O(n\sqrt{n})$