文章目录
- 题目 1525: 蓝桥杯算法提高VIP-找素数
- 分析
- 代码
- 通过截图
- 题目 1464: 蓝桥杯基础练习VIP-分解质因数
- 分析
- 代码
- 通过截图
题目 1525: 蓝桥杯算法提高VIP-找素数
时间限制: 1Sec 内存限制: 128MB 提交: 2503 解决: 347
题目描述
给定区间[L, R] , 请计算区间中素数的个数。
输入
两个数L和R。
数据规模和约定
2 < = L < = R < = 2147483647
R-L < = 1000000
输出
一行,区间中素数的个数。
样例输入
2 11
样例输出
5
分析
- 这题不管是用简单的试除法或者简单的埃氏筛,前者容易超时,后者容易爆空间!!!
- 所以这里的开辟空间,写入状态都有一定技巧。比如我们不要去开b个空间,看看b的范围,这样容易爆空间!!
- 记得,我们前面说过,埃氏筛适用于10的7次方规模的数据量,但R-L是10的6次方刚好小于这个范围,所以可以用埃氏筛。比如我区间为[10000,20000],我开辟10001个空间(10000到20000有10001个空间),如果10000对应空间0,10001对应空间1,10002对应空间2。
发现规律了吗?
n对应的空间为n-10000(即n-a)
- 首先,我们应该知道判断区间[a,b]是不是质数,用试除法只需要到根号b向上取整即可。这就是埃式筛子的范围。前面与埃氏筛的做法一样,乘以相应倍数,标记非素数的状态为false。
- 我们需要知道我们筛子的数据(2,3,5…)筛区间数据[a,b]的起始点。这里稍微思索一下,不难得出起始点为
math.ceil(a/i)*i
,这个大家可以稍微举例一下,用归纳法也可以。 - 筛区间数据这里是导致我刚开始没满分的地方(坑!!!):由于区间数据和筛子的数据可能重复,所以与i重复的一定要定为True(因为前提是i是质数)
代码
import math
a,b = map(int,input().split())
m = int((math.sqrt(b)+1))
flag = [True]* (m+1)
nums = [True]*(b-a+1)
flag[1] = False
# 将筛子做好
for i in range(2,m):
if flag[i]: # 是质数
for z in range(i*i,m+1,i):
flag[z] = False
for j in range(math.ceil(a/i)*i,b+1,i):
if j == i:
nums[i-a] = True
else:
nums[j-a] = False
res = 0 # 记录素数个数
for i in nums:
if i:
res+=1
print(res)
通过截图
题目 1464: 蓝桥杯基础练习VIP-分解质因数
时间限制: 1Sec 内存限制: 128MB 提交: 3994 解决: 2355
题目描述
求出区间[a,b]中所有整数的质因数分解。
提示
先筛出所有素数,然后再分解。
数据规模和约定
输入
输入两个整数a,b。
2< =a< =b< =10000
输出
每行输出一个数的分解,形如k=a1*a2*a3...(a1< =a2< =a3...,k也是从小到大的)(具体可看样例)
样例输入
3 10
样例输出
3=3
4=2*2
5=5
6=2*3
7=7
8=2*2*2
9=3*3
10=2*5
分析
- 小数据试除法去做就好了,不用想太多。
如果是大数据的话,考虑用埃筛法,先筛选出可能的质因数,直接用数和质因数进行操作。
- 感觉会比较复杂。因为有可能重复,其实在python里面只要找出所有质因数,然后再拼接(用
'*'
),会好一点。当时没想那么多,就直接完全模拟下来了。所以会看到重复的代码(也有可能是我逻辑比较混乱吧) - 首先我们寻找质因数的范围为
(2,math.ceil(math.sqrt(n)+1))
,这个不过多解释。用flag标记是不是最后一个质因数。 - 如果a!=i 且a能整除i:证明i是a的其中一个质因数,更新a,判断a是否能再被i整除:如果可以,再打印i并更新a。时刻注意a如果等于i,绝对会是最后一位,因为前面已经被筛掉了,证明a必定是一个质数。
- 但如果a一开始就是质数或者质因数是质数,那么我们可能筛选不到,所以循环结束没有标记也证明他本身或者最后一位就是质数,打印他,这样在a的更新中,a可能变为浮点数,所以要int取整一下。
- 代码逻辑不难, 但有点绕,还不是最清晰的,这点也是我可以继续进步的地方,争取以后可以写出更易懂的代码。
代码
import math
def fuc(n):
print(n,end=
a = n #
while 1:
flag = 0 # 标记是否是最后一位
for i in range(2,math.ceil(math.sqrt(n)+1)):
if a % i == 0 and a != i: # 证明不是最后一位
print(i,end="*")
a = a / i # 由于能整除,更新a
while a % i == 0: # 继续能整除
if a == i:
print(i)
flag = 1
break
print(i,end="*")
a = a/i
if flag:
break
if a == i:
print(i)
flag = 1
break
if not flag: # 证明最后一个数是素数
print(int(a)) # 由于除a会变成浮点,所以要转化
break
a,b = map(int,input().split())
for i in range(a,b+1):
fuc(i)
通过截图
如有错误,敬请指正,欢迎交流,谢谢♪(・ω・)ノ