IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 第13届蓝桥杯国赛Python B组 题目B解题思路 -> 正文阅读

[Python知识库]第13届蓝桥杯国赛Python B组 题目B解题思路

试题B: 小蓝做实验

【问题描述】
小蓝很喜欢科研,他最近做了一个实验得到了一批实验数据,一共是两百万个正整数。如果按照预期,所有的实验数据 x 都应该满足 10? ≤ x ≤ 10?。但是做实验都会有一些误差,会导致出现一些预期外的数据,这种误差数据 y 的范围是 103≤ y ≤ 1012 。由于小蓝做实验很可靠,所以他所有的实验数据中 99.99% 以上都是符合预期的。小蓝的所有实验数据都在 primes.txt 中,现在他想统计这两百万个正整数中有多少个是质数,你能告诉他吗?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。


【思路分析】

临到最后了这道题才想出来怎么做,,,没交上去,亏了

这个题有200w个数,直接暴力找肯定不行。我一开始走了弯路子,多线程,素数判断优化都用上了。最后才发现我想多了,比赛结束前1分钟才把数爆出来,也没时间写针对大数的素性测试了。。思路如下:

  1. 首先观察数据,均以1、3、5、7结尾。大于1000且结尾为5的数,肯定能被5整除,于是先利用编辑器正则替换所有以5结尾的数,此时剩下约150w多个数:

    \d+?5
    
    

使用埃氏筛选法,获得10^8以内的所有质数,这里注意,利用埃氏筛选法需要进行优化,不然也是跑的头大。我在之前博客里也写过直接判断质数的优化方法,除了2、3,所有质数均位于6n左右。因此可以直接将埃氏筛选法的步长拉到6,这样速度能进一步提升,然后影响埃氏筛选法速度的大头主要是2、3、5,需要进行多次循环才能筛掉后边的合数,因此预处理在生成列表时直接将2、3、5的倍数归0。理论上直接归零的质数倍数越多,生成素数就越快。

计数质数 Python 埃氏筛选法_AYO_YO的博客-CSDN博客

判断质数 Python Java C++_AYO_YO的博客-CSDN博客

def getprimes(n):
    ls = [i if i % 2 != 0 and i % 3 != 0 and i % 5 != 0 else 0 for i in range(n + 1)]
    ls[1], ls[2], ls[3], ls[5] = 0, 2, 3, 5
    for i in range(6, n + 1, 6):
        f = i - 1
        if f != 0:
            for j in range(2 * f, n + 1, f):
                ls[j] = 0
            continue
        f = i + 1
        if f != 0:
            for j in range(2 * f, n + 1, f):
                ls[j] = 0
    return filter(lambda x: x != 0, ls)
  1. 埃氏筛选法筛选 1 0 8 10^8 108以内的质数大概需要2分钟左右,再大恐怕就难以承受了。于是先将 1 0 8 10^8 108的质数统计出来,并把大于 1 0 8 10^8 108的质数拎出来。得到结果 1 0 8 10^8 108以内的质数有506733个。大数有约130个。

    506733
    [542693491967, 142787902577, 452440529173, 663634895869, 71242929179, 999870483413, 441673697183, 895134836909, 59008094959, 812048153483, 153230177243, 5986461211, 825268545161, 85386152959, 305669636917, 176618331487, 627185459239, 517233054923, 347714268719, 75380450897, 652349118967, 746710276723, 887316078643, 55623754253, 726602124691, 63723051253, 11944000489, 14326008041, 995344474081, 127374806651, 101228446879, 782792370337, 7616731547, 672817895497, 309261587441, 993510068537, 898280626321, 691250724803, 436362423451, 135244424501, 873959450791, 404517752423, 803431472291, 890481756773, 299729772337, 993254812121, 939705423281, 928689411767, 950796808643, 925182899009, 867933942403, 177084914339, 374154056921, 195931411013, 636268614181, 845966263637, 669349089677, 279219681547, 116772294307, 458677064359, 414099720659, 553029935971, 225122592047, 523383194647, 291752440213, 29190046721, 756126896941, 400963923179, 807339716593, 666619632839, 792597812483, 157223341237, 515677221383, 869902952023, 277744493561, 279840195947, 12066121523, 659914745389, 796743912131, 973038777059, 856703807231, 66169702601, 987064845247, 916671221021, 884623305749, 504935549881, 232438712231, 701919604183, 542037833447, 521942095081, 726449610001, 840499018589, 492469281101, 757165962919, 437417377471, 903288533789, 254110134101, 265121359891, 776841707227, 854559132599, 325401328397, 675731682791, 730947154187, 280786162939, 670729451441, 48996391291, 286681507897, 847973529401, 166381727761, 568868879153, 56085663143, 417414542761, 666771906149, 857635614683, 188918440631, 490214446741, 82741563491, 411523187461, 304024439243, 912661149107, 556591023551, 934801057481, 828742723319, 814141769183, 528476615281, 560425065263, 224638484077, 610321268093, 655599334577, 624348698849]
    

这些大数直接判断是否是质数也是相当恐怖的,于是判断特大数是否是质数,就要用另一个方法——费马素性测试。这个是我之前算法课期末作业研究过的一个算法,就是利用随机数随机对大数取余,如果能整除,就不是质数;加入了一个优化,加入了一个互质判断,大大提升了算法效率以及准确率。

for p in bigNum:
    K = 100 # 取随机数验证的次数,该次数越大,准确率越高。实测K=10就能得到准确结果了
    k = 0
    while k < K:  # 这里用while是后续判定随机完成率是否是100%
        b = int(random.random() * (p - 1) + 1)  # 生成一个1~p-1之间的随机整数
        factor = math.gcd(b, p)  # 计算b,p的最大公约数
        r = runFermatPower(b, p, p)  # 计算b^p mod p
        print(f"第{k + 1}次取随机数, 随机数b={b}, {b}{p}的最大公约数为{factor}, r=({b}^{p})mod p={r}", end=', ')
        if factor > 1:
            print(f"因b={b}与p={p}的最大公约数为{factor},不为互质数,故p={p}为合数")
            break
        elif r != b:
            print(f"因r={r},({b}^{p}) mod p ={r}!={b}, 故p={p}为合数")
            break
        else:
            print(f"故p={p}可能为素数")
            k += 1
    if k == K:
        print(f"经过{K}次循环验证, p={p}可能为素数, n为素数的概率为{(1 - 1 / (2 ** k)) * 100}%")
  1. 得到最终结果:

    506753
    

【完整代码】

比赛过程中的代码是分步骤的,一步步写,然后得到结果后再计算下一步,这个代码是优化过的完整版代码,直接运行就能得到最终结果。

B.py · AYO/Algorithm - 码云 - 开源中国 (gitee.com)

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-06-23 00:52:48  更:2022-06-23 00:53:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:20:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码