数论——质数讲解

质数讲解

质数

定义:质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。或叫素数。否则称为合数,规定1既不是素数也不是合数

在整个自然数集合中,质数数量不多,分布稀疏,对于一个足够大的整数N,不超过N的质数大约有 N / l n N 个 N/lnN个 N/lnN

判断质数

试除法

例题

给定 n 个正整数 ai,判定每个数是否是质数。

输入格式
第一行包含整数 n。

接下来 n 行,每行包含一个正整数 ai。

输出格式
共 n 行,其中第 i 行输出第 i 个正整数 ai 是否为质数,是则输出 Yes,否则输出 No。

数据范围
1≤n≤100,
1≤ai≤2^31−1
输入样例:
2
2
6
输出样例:
Yes
No
方法1 :假设要判断的数是n, 枚举2 ~ n - 1这些数,如果这些数中存在能够整除n的数,则说明n是合数,否则为质数

n = int(input())

def is_prime(x) :
	if x < 2 :
		return False
	for i in range(2, x) :
		if x % i == 0 :
			return False
	return True
for i in range(n) :
	x = int(input())
	if is_prime(x) :
		print("Yes")
	else :
		print("No") 

这个算法的时间复杂度是O(n)

方法2 :改进方法1,我们知道如果存在d | n,那么n的另一个因子为n / d,则(n / d)| n。所以我们只要枚举min(d, n / d)中的数,for(i = 2 ; i < n / d ; i++)

n = int(input())

def is_prime(x) :
	if x < 2 :
		return False
	i = 2
	while i <= x // i :
		if x % i == 0 :
			return False
		i += 1 
	return True
for i in range(n) :
	x = int(input())
	if is_prime(x) :
		print("Yes")
	else :
		print("No") 

优化后的时间复杂度为O(sqrt(n))

求解数的质因子

概要

质因子(或质因数)在数论里是指能整除给定正整数的质数。根据算术基本定理,不考虑排列顺序的情况下,每个正整数都能够以唯一的方式表示成它的质因数的乘积。

在这里插入图片描述

一个数n最多只有一个大于根号n的质因子

试除法

例题

给定 n 个正整数 ai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。

输入格式
第一行包含整数 n。

接下来 n 行,每行包含一个正整数 ai。

输出格式
对于每个正整数 ai,按照从小到大的顺序输出其分解质因数后,每个质因数的底数和指数,每个底数和指数占一行。

每个正整数的质因数全部输出完毕后,输出一个空行。

数据范围
1≤n≤100,
2≤ai≤2×109
输入样例:
2
6
8
输出样例:
2 1
3 1

2 3

n = int(input())

def divide(x) :
    i = 2
    while i <= x // i :
    	if x % i == 0:
    		s = 0
    		while x % i == 0 :
    			s += 1
    			x //= i
    		print(i, s)
    	i += 1
    if x > 1 :
        print(x, 1)
    print()

for i in range(n) :
    a = int(input())
    divide(a)

说明一下,由于从小到大枚举质数个数,一个阶段i的x中不会存在(1 ~ i - 1)的质因子,这样也一定不会存在一个合数i能整除它。

筛质数

两种筛法
给定一个正整数 n,请你求出 1∼n 中质数的个数。

例题

输入格式
共一行,包含整数 n。

输出格式
共一行,包含一个整数,表示 1∼n 中质数的个数。

数据范围
1≤n≤106
输入样例:
8
输出样例:
4
难度:简单
时/空限制:0.2s / 64MB

埃氏筛法

埃拉托斯特尼筛法,简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。

算法步骤

试除法枚举所有数,在枚举的过程中将质数的倍数全部筛为合数,只要后面的数未被判断为合数,那就是质数

N = 1000010
prime = []
st = [True] * N

n = int(input())

def get_prime(x) :
   cnt = 0
   for i in range(2, n + 1) :
       if st[i] :
           cnt += 1
           prime.append(i)
       j = i + i
       while j <= x :
           st[j] = False
           j += i
   return cnt
            
print(get_prime(n))

线性筛

在埃氏筛的基础上保证每个数都是由其最小质数筛掉的

N = 1000010
prime = []
st = [True] * N

n = int(input())

def get_prime(x) :
    cnt = 0
    for i in range(2, x + 1) :
        if st[i] : 
            prime.append(i)
            cnt += 1
        for j in prime :
            if i * j > n :
                break
            st[i * j] = False
            if i % j == 0 :
           	    break
    return cnt
            
print(get_prime(n))

线性筛的精髓if i % j == 0 : break,保证了每次都不会用更大的质因子更新,且避免了重复更新

总结

大二密码学用过的数论全都还回去了,质数的讲解有助于我们更好的更快的判断质数,找到质因子,列出一定范围内的质数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值