ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

codility 11-2 CountSemiprimes

2021-12-19 23:58:38  阅读:176  来源: 互联网

标签:11 CountSemiprimes 10 prime 质数 codility count dict semiprime


最近看到挺有意思的一题,原题链接:https://app.codility.com/programmers/lessons/11-sieve_of_eratosthenes/count_semiprimes/

题目描述
质数是一个正整数X,它有两个不同的除数:1和X。最初的几个质数是2、3、5、7、11和13。
半质数(semiprime)是一个自然数,它是两个质数的乘积(不一定是不同的)。前几个半素数是4,6,9,10,14,15,21,22,25,26。

给定两个非空数组 P 和 Q,每个数组由 M 个整数组成。这些数组表示有关指定范围内半素数个数的查询,返回 [ P[k], Q[k] ] 左闭右闭区间半质数的个数,其中1≤ P [ K ] ≤ Q [ K ]≤ N。

例如:P = [1, 4, 16], Q = [26, 10, 20] , 返回 [10, 4, 0]

P[0], Q[0] -->  [1, 26] 中间半质数有4,6,9,10,14,15,21,22,25,26, 共 10 个
P[1], Q[1] -->  [4, 10] 中间半质数有4,6,9,10, 共 4 个
P[2], Q[2] -->  [16, 20] 中间半质数共 0 个

思路与实现
由于1 ≤ P[K] ≤ Q[K] ≤ N,所以先存 0 到 N 每个数到当前数的半质数个数: dict = {数:到当前数的半质数个数},这样对于每个 P[k] 到 Q[k] 区间,只需要计算dict[Q[k]] - dict[P[k]],当 P[k] 为半质数时需要 +1。

如何求 0 到 N 每个数到当前数 x 的半质数个数,可以简单描述为 dict[x] = dict[x-1]+1 if x是半质数 else dict[x-1]

然后问题来到如何求一个数 x 是否是半质数:将 x 拆成两个数的乘积,再判断这两个数是否都为质数。又因为将 x 拆成两个数的乘积,一定有一个数小于根号 x,所以只需要遍历到根号 x 来降低复杂度。

def solution(N, P, Q):
    res = []

    # 寻找N内半质数
    semiprime_dict = {}
    prime_nums = set()  # 存质数,不用重复判断,节省空间也可以不要
    for i in range(2, int(N**0.5)+1):
        # 不是质数
        if i not in prime_nums and not is_prime(i):
            continue
        prime_nums.add(i)
        for j in range(i, int(N/i)+1):
            if j not in prime_nums and not is_prime(j):
                continue
            # 如果i, j 都是质数
            prime_nums.add(j)
            # 半质数加入semiprime_dict中
            semiprime_dict[i*j] = 0

    # semiprime_dict={数:到当前数的半质数个数} 当前只有半质数,将 semiprime_dict 扩展到所有数
    # (实现的有点复杂
    semiprimes = sorted(semiprime_dict)  # 排序后的键值
    count = 0
    for x in semiprimes:   # 对于每个半质数,到当前的半质数个数
        count += 1 
        semiprime_dict[x] = count
    semiprime_dict[0] = 0  # 1,2,3都应该是0,加入0是解决P[i]=1的情况
    for x in range(1, N+1):		# 非半质数,到当前的半质数个数与前一个相同
        if x not in semiprime_dict:
            semiprime_dict[x] = semiprime_dict[x-1]
    
    # 找 P[i]-Q[i]之间semiprime_list的元素个数 O(M)
    for i in range(len(P)):
        count = semiprime_dict[Q[i]] - semiprime_dict[P[i]]
        if semiprime_dict[P[i]] > semiprime_dict[P[i]-1]:
            count += 1
        res.append(count)

    return res

# 判断质数
def is_prime(x):
    # 偶数一定不是质数
    if x != 2 and x % 2 == 0:
        return 0 
    # x 拆成两个数的乘积一定有一个小于根号x
    for i in range(2, int(x**0.5)+1):
        if x % i == 0:
            return 0

    return 1

标签:11,CountSemiprimes,10,prime,质数,codility,count,dict,semiprime
来源: https://blog.csdn.net/weixin_42694380/article/details/122031895

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有