热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【蓝桥杯】简单数论3——素数

1、素数判断素数定义:只能被1和自己整除的正整数。注:1不是素数,最小素数是2。判断一个数n是不是素数:当n≤时,用试除法;n时,试

1、素数判断

素数定义:只能被1和自己整除的正整数。注:1不是素数,最小素数是2。

判断一个数n是不是素数:当n≤10^{14}时,用试除法;n>10^{14}时,试除法不够用,需要用高级算法,例如Miller_Rabin算法。

试除法:用[2, n-1]内的所有数去试着除n,如果都不能整除,就是素数。


  • 优化1:把[2, n-1]缩小到[2, √n]。证明:若n= a×b,其中a≤√n,b>√n,如果n有个因子是a,说明n不是素数,b不用再试。
  • 优化2:提前算出[2, √n]范围内的所有素数,用这些素数来除n就行了。埃氏筛用到这一原理。范围[2,√n]内有多少个素数?在1百万以内,约有7.8万个素数;在1亿以内,约有576万个素数,提高了十几倍的速度。但一般只需要用优化1即可。

from math import*
def is_prime(n): #若n是素数,返回true
if n == 1: return False #1不是素数
m = int(sqrt(n)+1) #sqrt(n),也可以这样写n**0.5
for i in range(2, m):
if n % i == 0:
return False #不是素数
return True #是素数

 例题一:选数

lanqiao0J题号753



题目描述


已知 n 个整数 1,2,⋯,x1​,x2​,⋯,xn​,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:


3+7+12=22            3+7+19=29            7+12+19=38            3+12+19=34。


现在,要求你计算出和为素数共有多少种。 例如上例,只有一种的和为素数:3+7+19=29。


输入描述


输入格式为:


第一行:n,k(1≤n≤20,k<n)


第二行:x1​,x2​,⋯,xn​(1≤xi​≤5×106)


输出描述


一个整数(满足条件的种数)。


输入输出样例


输入


4 3
3 7 12 19


输出


1

先得到从s中选出k个的所有组合,使用combinations()函数,然后判断这些组合的和是否为素数。

from math import *
from itertools import * # combinations(s,k)需要导入这个库
def is_prime(n):
if n == 1: return False
m = int(sqrt(n)+1)#sqrt(n)可以这样写n**0.5
for i in range(2, m):
if n % i == 0: return False
return True
n, k = map (int, input ().split())
s = list (map(int, input ().split()))
cnt = 0
for e in combinations(s,k): # 从s中选出k个的所有组合
num= sum(e) #求和
if is_prime (num) == True: cnt+=1
print(cnt)

例题二:笨小猴 

lanqiao0J题号527



题目描述


笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!


这种方法的具体描述如下:假设 maxn 是单词中出现次数最多的字母的出现次数,minn 是单词中出现次数最少的字母的出现次数,如果 maxn−minn 是一个质数,那么笨小猴就认为这是个 Lucky Word,这样的单词很可能就是正确的答案。


输入描述


输入一行,是一个单词,其中只可能出现小写字母,并且长度小于 100。


输出描述


输出两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出Lucky Word,否则输出No Answer;


第二行是一个整数,如果输入单词是 Lucky Word,输出 maxn−minn 的值,否则输出 0。


输入输出样例


示例 1


输入


error


输出


Lucky Word
2


示例 2


输入


Olympic


输出


No Answer
0

模拟,统计每个字母出现的次数s.count(i),然后判断maxn-minn是否为素数。

from math import *
def is_prime(n):
if n == 0 or n==1:return False
m = int(sqrt(n)+1)
for i in range(2,m):
if n%i == 0: return False
return True
s = input()
maxn= -1 # 反向初始化(最大值初始化为最小,最小值初始化为最大)
minn= 1000
for i in s: # 找出最最小值
n=s.count(i)
maxn=max(maxn,n)
minn=min(minn,n)
if is_prime(maxn-minn):print("Lucky Word");print(maxn-minn)
else: print("No Answer");print(0)

例题三: 最大最小公倍数

lanqiao0J题号1510



题目描述


已知一个正整数 N,问从 1∼N 中任选出三个数,他们的最小公倍数最大可以为多少。


输入描述


输入一个正整数 N。1≤N≤10^6。


输出描述


输出一个整数表示答案。


输入输出样例


输入


9


输出


504


思路:贪心


  • 贪心题,从大的数开始选。不过,简单地把N里面最大的三个数相乘,N*(N-1)*(N-2),并不正确,需要分析多种情况。
  • 最小的公倍数是三个数的质因数相乘,如果有几个质因数相同,则比较两数中哪个数的质因数的个数较多。例如6、7、8的最小公倍数,先分解因子:6=2×3,7=7×1,8=2×2×2,它们的最小公倍数是3×7×2×2×2。
  • 大于1的两个相邻整数互质,它们没有公共的质因数。如果题目是任选二个数,最大的最小公倍数是N*(N-1)

对于连续的最大三个整数,分两种情况:
(1)N是奇数。N、N-1、N-2是奇偶奇,结论是这三个数两两互质,三个数的乘积就是最大的最小公倍数。三个数两两互质,也就是说任意一个质数,只在N、N-1、N-2中出现一次。连续的三个整数的质因数必有2和3,奇数N的质因数可能仅有3,但有且仅有N-1有质因数2。所以N是奇数,那么N、N-1、N-2互质。



证明:下面对这两个质数分析:


  • 质因数2,只在N-1中出现。
  • 质因数3,如果在N中出现(设N=3a,a为整数),就不会在N-1中出现(这要求N-1 = 3b,,n为整数,N无整数解),也不会在N-2中出现(这要求N-2= 3b,N无整数解)。

结论:推广到任何一个质数k,都只会在N、N-1、N-2中出现一次,所以三个数互质。

(2)N是偶数。 N的质因数要么有2和3两个质数,要么有2一个质数


  • 质因数2,N和N-2有公因子2;
  • 质因数3,若设N= 6a,N-1=6b, N-2=6c。由上面质因数3的分析可知,质数3只会出现在N中

结论:如果偶数N中有质因数3,那么N、N-1、N-2互质,否则N、N-1、N-3互质(因为只有N有质因数2)。

n = int(input())
if n <&#61; 2: print(n)
elif n % 2 !&#61; 0: # n是奇数
print(n * (n - 1) * (n - 2))
else: # n是偶数
if n % 3 &#61;&#61; 0: print((n-1)*(n-2)*(n-3))# n有因数3
else:print (n*(n-1)*(n-3)) # n没有因数3

 2、素数筛

  • 素数的筛选:给定n&#xff0c;求2~n内所有的素数。
  • 一个个地判断很慢&#xff0c;所以用“筛子”筛所有的整数&#xff0c;把非素数筛掉&#xff0c;剩下的就是素数。
  • 常用两种筛法&#xff1a;埃氏筛、欧拉筛。

2.1埃氏筛

初始队列{2、3&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;7&#xff0c;8&#xff0c;9&#xff0c;10&#xff0c;11&#xff0c;12&#xff0c;13&#xff0c;...&#xff0c;n}&#xff0c;操作步骤:
...
(1&#xff09;输出最小的素数2&#xff0c;筛掉2的倍数&#xff0c;得{3&#xff0c;5&#xff0c;7&#xff0c;9&#xff0c;&#xff0c;11&#xff0c;13&#xff0c;...}

(2&#xff09;输出最小的素数3&#xff0c;筛掉3的倍数&#xff0c;得{5&#xff0c;7&#xff0c;11&#xff0c;13&#xff0c;...}

(3&#xff09;输出最小的素数5&#xff0c;筛掉5的倍数&#xff0c;得{7&#xff0c;11&#xff0c;13&#xff0c;...}

继续以上步骤&#xff0c;直到队列为空。


例题四&#xff1a;质数&#xff08;模板题&#xff09;

lanqiao0J题号1557​​​​​​​



题目描述


给定一个正整数 N&#xff0c;请你输出 N 以内&#xff08;不包含 N&#xff09;的质数以及质数的个数。


输入描述


输入一行&#xff0c;包含一个正整数 N。1≤N≤1000


输出描述


共两行。


第 1 行包含若干个素数&#xff0c;每两个素数之间用一个空格隔开&#xff0c;素数从小到大输出。


第 2 行包含一个整数&#xff0c;表示N以内质数的个数


输入输出样例


输入


10


输出


2 3 5 7
4


  • vis[i]记录数i的状态&#xff0c;若vis[i]&#61;1,表示它被筛掉&#xff0c;不是素数。
  • prime[ ]存放素数,prime[0]是第一个素数2。
  • E_sieve(n)函数用来做筛除的数2、3、5......等&#xff0c;最多到\sqrt{n}就可以了。例如&#xff0c;求n &#61;100以内的素数&#xff0c;用2、3、5、7筛就足够了。原理和试除法一样:非素数k&#xff0c;必定可以被一个小于等于的素数整除,被筛掉。

from math import *
def E_sieve(n) : # 埃氏筛
for i in range (2,int (sqrt(n)&#43;1)):
if not vis[i]: # 没有被筛过&#xff0c;是素数
for j in range(i*i, n&#43;1,i): # 开始筛该素数的倍数
vis[j] &#61; 1
k&#61;0
for i in range (2, n&#43;1): #存素数
if not vis[i]: # 没有被筛
prime[k] &#61; i # 是素数。可以不需要用prime存&#xff0c;直接打印即可print(vis[i],end&#61;" ")
k &#43;&#61; 1
return k
N&#61; int(1e6)
prime &#61;[0]*N
vis &#61; [0]*N
n &#61; int (input())
k&#61; E_sieve(n-1)
for i in range (0,k): print (prime[i], end&#61;" ")
print ()
print (k)

 3、区间素数

埃氏筛法求[2, n]内的素数&#xff0c;只能解决规模n<10^7的问题。如果n更大&#xff0c;在某些情况下&#xff0c;也可以用埃氏筛法来处理&#xff0c;这就是大区间素数的计算。
把埃氏筛法扩展到求区间[a, b]的素数&#xff0c;a&#xff0c;b-a≤10^6

方法:先用埃氏筛法求[2,\sqrt{n}]内的素数&#xff0c;然后用这些素数来筛[a,b]区间的素数


例题五&#xff1a;找素数(模板题)

lanqiao0J题号1558



题目描述


给定一个区间 [a,b]&#xff0c;请你求出该区间内有多少个素数。


输入描述


输入共一行&#xff0c;包含两个整数 a,b。


2≤a≤b≤2^{31}&#xff0c;b−a≤1000000


输出描述


输出一个整数&#xff0c;表示答案。


输入输出样例


输入


2 6


输出


3


题解&#xff1a; 

本题a&#xff0c;b<&#61; 2^{31} ,不能直接定义一个vis[N]&#xff0c;N&#61;2^{31}来表示[0,b]内的每个数字&#xff0c;空间太大。
只能定义区间大小的空间&#xff0c;即N&#61;1000000。

from math import *
def seg_sieve(a, b):
for i in range(2,int(sqrt(b))&#43;1): # 先用埃氏筛求2~√n的素数
if vis[i]&#61;&#61; True: # 是素数
for j in range(i*i,int(sqrt(b)),i):
vis[j]&#61;False
# 再求[a, b]的素数
for j in range(max(2,(a&#43;i-1)//i)*i, b&#43;1,i): # 难点&#xff1a;处理起点&#xff1a;max(2,(a&#43;i-1)//i)*i&#xff0c;从当前素数i的倍数开始筛
seg_prime[j-a]&#61;False
num&#61; 0
# 统计[a, b]的素数个数
for i in range(0, b-a&#43;1):
if seg_prime[i]:
prime[num] &#61; i&#43;a
num &#43;&#61; 1
print(num)
N &#61; 1000005 # 稍微大一点&#xff08;保险)
vis &#61; [True]*N # 标记[2, sqrt(b)]是否为素数
prime &#61; [0]*N # 存[a, b]的素数
seg_prime &#61; [True] * N # 标记[a, b]是否为素数
a, b &#61; map(int,input ().split())
seg_sieve(a,b)

4、分解质因子

任何一个正整数n都可以唯一地分解为有限个素数的乘积&#xff1a;n&#61;p_1^{c1}p_2^{c2}...p_m^{cm}&#xff0c;其中c_i都是正整数&#xff0c;p_i都是素数且从小到大
分解质因子也可以用试除法。求n的质因子:
(1)第一步&#xff0c;求最小质因子p_1。逐个检查从2到\sqrt{n}的所有素数&#xff0c;如果它能整除n&#xff0c;就是最小质因子。然后连续用p_1除n&#xff0c;目的是去掉n中的p_1&#xff0c;得到n_1

 (2&#xff09;第二步&#xff0c;再找n_1的最小质因子。逐个检查从p,到的所有素数。从p_1开始试除&#xff0c;是因为n_1没有比p_1小的素因子&#xff0c;而且n_1的因子也是n的因子。

 (3&#xff09;继续以上步骤&#xff0c;直到找到所有质因子。


例题六&#xff1a;寻找质因子 

题目描述


给定一个区间 [a,b]&#xff0c;请你求出区间 [a,b] 中所有整数的质因数分解。


输入描述


输入共一行&#xff0c;包含两个整数 a,b。


2≤a≤b≤10000。 


输出描述


每行输出一个数的分解&#xff0c;形如 k&#61;a1​×a2​×a3​⋯(a1​≤a2​≤a3​⋯&#xff0c;k也是从小到大的)(具体可看样例)


输入输出样例


输入


3 10


输出


3&#61;3
4&#61;2*2
5&#61;5
6&#61;2*3
7&#61;7
8&#61;2*2*2
9&#61;3*3
10&#61;2*5


题解&#xff1a;

直接对每个数进行分解,然后打印出它的因数。

def s(x):#返回x的第一个因子
for i in range(2,int(x**0.5)&#43;1):
if x%i&#61;&#61;0:return i
return x # 若没有找到因子&#xff0c;返回本身
a, b &#61; map(int,input ().split())
for x in range(a, b&#43;1):
print(x,end&#61;"") ; print( &#39;&#61;&#39;, end&#61;"")
while x!&#61;1:
ans &#61; s(x) # 求最小质因数
if x/ans !&#61; 1: print(ans, end&#61;"") ; print(&#39;*&#39;, end&#61;"")
else:print (int(ans)) # 质因子是本身&#xff0c;直接输出
x /&#61;ans # 除掉最小质因子&#xff0c;继续找下一个最小质因子

例题七&#xff1a;数的拆分

2022年第十三届省赛lanqiao0J题号2090



问题描述


给定 T 个正整数 ai​, 分别问每个 ai​ 能否表示为 x1^{y1}*x2^{y2}的形式, 其中 x1​,x2​ 为正整数, y1​,y2​ 为大于等于 2 的正整数


输入格式


输入第一行包含一个整数 T 表示洵间次数。


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


输出格式


对于每次询问, 如果 ai​ 能够表示为题目描述的形式则输出 yes, 否则输出 no.


样例输入


7
2
6
12
4
8
24
72


样例输出


no
no
no
yes
yes
no
yes


样例说明


第 4,5,74,5,7 个数分别可以表示为:


a4​&#61;2^2*1^2


a5​&#61;2^3*1^2


a7​&#61;2^3*3^2


评测用例规模与约定


对于 10%1 的评测用例, 1≤T≤200,ai​≤10^9;


对于 30% 的评测用例, 1≤T≤300,ai​≤10^18;


对于 60% 的评测用例, 1≤T≤10000,ai​≤10^18;


对于所有评测用例, 1≤T≤100000,1≤ai​≤10^18



 题解&#xff1a;

例:24不行&#xff0c;因为24&#61;3^1*2^3。72可以&#xff0c;因为72&#61;2^3*3^2
数据规模ai≤10^{18}&#xff0c;即使用之前的优化方法&#xff1a;遍历2~\sqrt{a_i}&#xff08;即2~10^9&#xff09;也是不能通过所有测评用例。​​​​​​​

对a进行素因子分解a&#61; p^{q1}_1p^{q2}_2
重点&#xff1a;题目要求q_i≥2&#xff0c;拆分q_i&#61;k_1y_1&#43;k_2y_2,k_1,k_2\geq 0,y_1,y_2\geq 2y_1&#61;2,y_2&#61;3可以保证所有q_i\geq 2均有非负整数解。
q_i&#61;ky_1&#43; ky_2&#61; 2k_1&#43;3k_2&#61; k对于任意k>1都有非负整数解&#xff0c;例如:


  • k %3&#61;0&#xff0c;k_1&#61;0&#xff0c;k_2&#61; k/3
  • k %3&#61;1&#xff0c;k_1&#61;2&#xff0c;k_2&#61;(k-4)/3
  • k %3&#61;2&#xff0c;k_1,&#61; 1&#xff0c;k_2&#61;(k-2)/3

问题变成a是否能分解为x_1^2x_2^3&#xff0c;检测每个q_i是否大于等于2&#xff0c;只要大于等于2&#xff0c;就可以按对应的k分配到x_1,x_2

本题a≤10^18&#xff0c;所以x_1^2x_2^3&#61;10^{18}&#xff0c;当素因子p >4000时p^5 \geqslant 10^{18}​​​​​​​&#xff0c;只需要暴力判断4000以内的素因子&#xff0c;对于大于4000的p&#xff0c;指数只能是2、3、4&#xff0c;判断是否为平方数或立方数即可

时间复杂度:
用埃氏筛预计算p&#61;.4000以内的素数&#xff0c;O(p^2)。
然后进行判断&#xff0c;O(T*550)&#xff0c;550是4000以内的素数个数。

from math import *
N &#61; 4000
prime &#61; [0]*N
vis &#61; [0]*N
cnt &#61; 0
def E_sieve(): # 预计算4000以内的素数
global cnt
for i in range(2,N):
if not vis[i]: cnt&#43;&#61;1; prime[cnt] &#61; i
for j in range(i*i,N,i):vis[j] &#61; 1
def solve() :
a &#61; int(input())
for i in range (1, cnt&#43;1): # 遍历4000以内所有素数
c &#61; 0 # 统计因子个数
while a % prime[i] &#61;&#61; 0: # 能被整除&#xff0c;
a/&#61;prime[i]
c&#43;&#61;1 # 次方&#43;1
if c&#61;&#61;1: print("no"); return # 次方数为1&#xff0c;不合题意
k &#61; int(sqrt(a))
if k*k &#61;&#61; a: print("yes"); return # 检查n是否为平方数
k &#61; int (pow(a,1/3))
if k*k*k&#61;&#61;a: print("yes"); return # 检查n是否为立方数
print("no")
E_sieve()
T&#61;int(input())
for i in range(T): solve()


推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • Day2列表、字典、集合操作详解
    本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • importjava.util.ArrayList;publicclassPageIndex{privateintpageSize;每页要显示的行privateintpageNum ... [详细]
  • 006_Redis的List数据类型
    1.List类型是一个链表结构的集合,主要功能有push,pop,获取元素等。List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
author-avatar
曾静ZHH_423
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有