[算法]素数和问题(python)

素数和问题

又名 寻找素数对

问题描述

Description

Given an even number ( greater than 2 ), return two prime numbers whose sum will be equal to given number. There are several combinations possible. Print only first such pair.

NOTE: A solution will always exist, read Goldbach’s conjecture.Also, solve the problem in linear time complexity, i.e., O(n).

Input

The first line contains T, the number of test cases. The following T lines consist of a number each, for which we’ll find two prime numbers.Note: The number would always be an even number.

Output

For every test case print two prime numbers space separated, such that the smaller number appears first. Answer for each test case must be in a new line.

Sample Input 1

5
74
1024
66 
8
9990

Sample Output 1

3 71
3 1021
5 61
3 5
17 9973

题目地址

题目解析

哥德巴赫猜想: 任意取出一个偶数(>2),来寻找两个素数,使得其和等于该偶数.
由于可以有不同的素数对来表示同一个偶数,输出素数对中第一个素数最小的那对

思路解析
  1. 创建一个数组,存放范围内的数
  2. 先判断给定范围内的数哪些是素数哪些不是,并更新数组
  3. 判断(i,n-i)是否同时为素数,有则返回结果
代码实现(python)
解法1

传统求质数方式,时间复杂度O(n√n)

# Generate all prime numbers less than n.
def SieveOfEratosthenes(n, isPrime):
    # Initialize all entries of boolean
    # array as True. A value in isPrime[i]
    # will finally be False if i is Not a
    # prime, else True bool isPrime[n+1]
    isPrime[0] = isPrime[1] = False
    for i in range(2, n + 1):
        isPrime[i] = True

    p = 2
    while (p * p <= n):

        # If isPrime[p] is not changed,
        # then it is a prime
        if (isPrime[p] == True):

            # Update all multiples of p
            i = p * p
            while (i <= n):
                isPrime[i] = False
                i += p
        p += 1


# Prints a prime pair with given sum
def findPrimePair(n):
    # Generating primes using Sieve
    isPrime = [0] * (n + 1)
    SieveOfEratosthenes(n, isPrime)

    # Traversing all numbers to find
    # first pair
    for i in range(0, n):
        if (isPrime[i] and isPrime[n - i]):
            print(i, (n - i))
            return

if __name__ == '__main__':
    case_num = int(input().strip())
    for i in range(case_num):
        N = int(input().strip())
        findPrimePair(N)




# This code is contributed by
# Smitha Dinesh Semwal
解法2

使用埃筛选法求质数,时间复杂度O(n log log n) 接近于 O(n)

# 埃式筛选法
def no_of_primes(n):
    no_list = [1] * (n + 1)
    no_list[0] = 0
    no_list[1] = 0
    for i in range(2, n + 1):
        if no_list[i] == 1:
            for j in range(2 * i, n + 1, i):
                no_list[j] = 0
    return no_list


if __name__ == '__main__':
    t = int(input().strip())
    for i in range(t):
        n = int(input())
        no_list = no_of_primes(n)
        for i in range(0, n):
            if no_list[i] == 1 and no_list[n - i] == 1:
                print(i, (n - i))
                break

解法3

使用欧式筛法求质数,时间复杂度 O(n)
欧式筛法博客

原理:,每个数都可以拆成一个最小的质因数(素数)和一个最大的合数,当遍历到那个最大的合数的时候,就依据最小的质因数将其筛选出去,这样每个数只被他最小的质因数筛选出去了一次,因此时间复杂度可以达到O(N)

算法而核心就在于这句

if a % b == 0: break

如何理解?

 筛选原则: 保证每个数都被其最小质因数(素数)筛去
 设i=a b=prime
 若 i % prime == 0,则有i = prime * b
 则用prime_next去约去 i * prime_next时候有 i * prime_next = prime * b * prime_next
 此时prime 小于 prime_next,如果用prime_next约去则不满足条件
 因此当遍历到b*(prime_next)时i * prime_next一定可以被prime约去,因此现在就不用约

 举个例子:
 设i =6 ,prime =2 prime_next =3
 若 6 * 2 ==0 ,则有6 = 2 * 3
 则用3去约去 6 * 3 =18时候,有 6 * 3 = 2 * 3 * 3
 此时2 <3 如果用3约去则不满足条件
 因此当遍历到3 * 3 = 9 时, 18一定可以被2约去,因此现在就不用约去18


(本图来自https://www.cnblogs.com/grubbyskyer/p/3852421.html )

def no_of_primes2(n):
    no_list = [1] * (n + 1)
    no_list[0] = 0
    no_list[1] = 0
    prime = []
    for a in range(2, n + 1):
        if no_list[a] == 1:
            prime.append(a)
        for b in prime:
            if a * b > n: break
            no_list[a * b] = 0
            if a % b == 0: break
    return no_list
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值