6.6 完数(project) educoder项目实训

前言

        在最近的Python课上,做到这样一个“有趣”的作业,求得前n个完数,并输出其与其真约数的约数的加和式子,刚开始没怎么在意这个题,想着不就是做过好几遍了的语言基础练习题嘛,但是接下来的几小时没想到都在肝这个,具体原因请继续往下看

第一关

到现在为止一切安好,就是基础语言练习题而已,秒了

代码

import math

def f(n):
    r = 1
    for i in range(2, int(math.sqrt(n))+1):
        if(n % i == 0):
            r += (i + n / i)
    return r == n

cnt,num = 0,2
x = int(input())
while cnt < x:
    num += 1
    if f(num):
        fac = [i for i in range(1,num) if num%i == 0]
        s = str(num) + '='
        for i in fac:
            s += str(i) + '+'
        print(s.rstrip('+'))
        cnt += 1

第二关

        我一看题目完全没变,寻思怎么能出一样的题目呢??然后直接ctrl c + ctrl v开始评测,正当我沉浸在题目秒了的喜悦中,我发现了这样一个东西

然后不出所料,没能在20s内完成任务,TLE了

于是我开始在网上搜寻有关完全数的数学知识,很快就找到了欧拉提出的完全数获得公式:

如果p是质数,且2^p-1也是质数,那么(2^p-1)* 2^(p-1)便是一个完全数。

用这样的办法改进一下代码还是很easy的,不久就得到了这样一个崭新出厂的代码

代码

import math

def is_prime(n):
    for i in range(2, int(math.sqrt(n))+1):
        if(n % i == 0):
            return False
    return True


cnt, num = 0, 2
x = int(input())
while cnt < x:
    if is_prime(num) and is_prime(2 ** num - 1):
        a = 2 ** (num-1) * (2 ** num - 1)
        s = str(a) + '='
        fac = [1]
        for i in range(2,2 ** num - 1):
            if(a % i == 0):
                fac.append(i)
                fac.append(a // i)
        fac.sort()
        print(s + str(fac).replace(', ','+').lstrip('[').rstrip(']'))
        cnt += 1
    num += 1

ac题目总是让人心情愉悦的,所以我顺势点开了下一关

 第三关

这回我学聪明了,先去看了看测试集,虽然有心理预警,但仍然吓了一跳

阶段1

当我看到这个9心里已经凉了一半了,另一半是当我cv提交测试没过的时候彻底凉透的,那么很显然需要一些数学上的优化,此时我想到如果单独将素数罗列出来,可以节省一次素性检验,只需检验 (2 ^ n) -1 是否也为素数即可,但是这样节约的时间仍然不足以让题目完全ac。

阶段2

此时我发现我做了太多的除法和模运算,对于大数的计算是很费时间的,于是我开始观察约数的序列,得到这样一个事实:除了 (2^n)-1 , 完数a的其他约数都是 2 ^ n的形式,于是我想到可以将他们特殊处理,这里把1也放进来是为了防止完数a本身也进入列表,此时已经可以ac题目了。

阶段3

但是150s的运行时间让我觉得下一关肯定也过不了,不如所性继续优化,于是我想起一种更快速的,类似于筛法的素性检验算法,更换了素性检验算法后时间降至50s左右,此时我再一次沉浸在喜悦之中

代码

import math


def is_prime(n):
    if n <= 1:
        return False
    if n <= 3:
        return True
    if n % 2 == 0 or n % 3 == 0:
        return False
    i = 5
    while i * i <= n:
        if n % i == 0 or n % (i + 2) == 0:
            return False
        i += 6
    return True


cnt = 0
prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61]
index = 0
x = int(input())
while cnt < x:
    # 欧拉的完数公式 : 如果 n 和  (2**n -1) 同为素数 则 (2^(n-1)) * ((2^n) -1)为完数
    if is_prime(2 ** prime[index] - 1):
        a = 2 ** (prime[index]-1) * (2 ** prime[index] - 1)
        s = str(a) + '='
        # 寻找约数
        fac = [1]
        for i in range(1, prime[index]):
            t = 2 ** i
            fac.append(t)
            fac.append(a // t)
        fac.sort()
        print(s + str(fac).replace(', ', '+').lstrip('[').rstrip(']'))
        cnt += 1
    index += 1

第四关

        此时内心想法其实是:第三关运行时间给了200s,第四关应该给的更多吧。但点进去一看,居然只有20s??!!而且这个测试集我&*%……&%¥#%

压抑住爆粗口的冲动,接着想优化的方法。

我先想着 2^(n)-1这样的数有没有什么特殊性质,然后发现这个东西叫做梅森数,而且发现,对于梅森数有着一种特殊的素性检验法,叫做lucas-lehmer检验法​​​​​​,这真是解决了大问题,然后我又发现,我所需要的素数序列,靠人力最多写到一百多,就要花很多时间在手动计算素数上了,这很不符合程序设计的理念(我要是自己算要程序干嘛!!!)那么曾经学过一种得到素数序列的犯法叫做欧拉筛法(也称线性筛法)就派上用场了,O(n)的时间复杂度太香了!!基本不会挤占我的运行时间。除此之外,我又将乘除法和阶乘等运算换成了对应的位运算,更尽可能的加速程序的运行,功夫不负有心人,终于解决了这样的问题,并且运行时间不到1s!!!(跨越性进步好耶!)

代码

import math


# 欧拉筛法获取小于r的素数列表
# 可以节省对每个n进行素性检验的过程,避免更多的计算
def oula(r):
    # 全部初始化为0
    prime = [0 for i in range(r+1)]
    # 存放素数
    common = []
    for i in range(2, r+1):
        if prime[i] == 0:
            common.append(i)
        for j in common:
            if i*j > r:
                break
            prime[i*j] = 1
            #将重复筛选剔除
            if i % j == 0:
                break
    return common


'''
卢卡斯-莱默素性检验法
令梅森数 M[p]=2^p-1作为检验对象,
定义数列 L[n]:L[n-1] ^ 2 - 2,n>0. 
这个数列的开始几项是4,14,194,37634,1416317954……
那么M[p]是质数当且仅当L[p-2] ≡ 0 (mod M[p])
否则Mp是合数。sp−2模Mp的余数叫做Mp的卢卡斯-莱默余数。
'''
def primality(N, M):
    if N == 2:
        return True
    s = 4
    for i in range(N-2):
        s = (s * s - 2) % M
    return s == 0


cnt,index = 0,0
prime = oula(2000)
# 可以刚好得到完数的 n,虽然可以节省一定时间,但通过答案倒推过程不符合程序设计的合理性
# res = [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279]
x = int(input())
while cnt < x:
    # 欧拉的完数公式 : 如果 n 和  (2**n -1) 同为素数 则 (2^(n-1)) * ((2^n) -1)为完数
    m = (1 << prime[index])- 1
    if primality(prime[index],m):
        a = m << (prime[index]- 1)
        s = str(a) + '='
        '''
        寻找约数
        观察数据不难得知,除了m,a其余的约数都是 2 ^ n 形式,
        这里初始化将1也放进来是避免 a 本身进入列表中
        那么我们通过这个结论,可以不再使用试除法获取约数列表
        节省更多的时间
        '''
        fac = [1,m,(m+1)>>1]
        num1 = 2
        num2 = a >> 1
        '''
        误区记录:insert具有O(n)的时间复杂度,相比append的O(1),
        虽然节省了排序的O(nlogn),但数据大时并不更省时。
        for i in range(1, factors[index]-1):
            fac.insert(i+2,num2)
            fac.insert(i,num1)
            num1 <<= 1
            num2 >>= 1
        '''
        for i in range(1, prime[index]-1):
            fac.append(num1)
            fac.append(num2)
            num1 <<= 1
            num2 >>= 1
        fac.sort()
        print(s + str(fac).replace(', ', '+').lstrip('[').rstrip(']'))
        cnt += 1
    index += 1

总结

        一个小小完数,居然涉及如此广泛的数论知识,深刻提醒我数学在计算机领域的运用确实是十分广泛的,学习算法的路上,数学一定是一大助力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/561649.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索设计模式的魅力:开启智慧之旅,AI与机器学习驱动的微服务设计模式探索

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索AI与机器学习驱动的微服务设计模式之旅✨ 亲爱的科技爱好者们&#xff0c;有没…

【独家推荐】视频下载神器:一键解决Mac/Win视频下载转换难题!

在信息爆炸的时代&#xff0c;视频已经成为我们获取知识和娱乐的重要途径。然而&#xff0c;很多精彩视频并没有提供直接的下载链接&#xff0c;这就给广大视频爱好者带来了不小的困扰。不过&#xff0c;现在有了这款专为Mac和Windows用户打造的视频下载转换器&#xff0c;一切…

Redux入门:使用@reduxjs/toolkit构建React应用程序状态管理

随着应用程序复杂性的增加,有效管理应用程序状态变得越来越重要。Redux是一种流行的状态管理解决方案,随着应用程序复杂性的增加,有效管理应用程序状态变得越来越重要。Redux是一种流行的状态管理解决方案,但传统的Redux设置和使用过程比较繁琐。幸运的是,Redux官方团队推出了r…

C语言实现贪吃蛇项目(2)

先来看看效果&#xff1a; 20240420_212115 文章目录&#xff1a; 3.项目实现3.0宽字符的打印3.01本地化操作setlocale函数宽字符的打印 3.1贪吃蛇结构的创建和维护3.11贪吃蛇结构的创建3.12贪吃蛇的维护 3.2初始化游戏3.21.打印欢迎界面、隐藏光标和设置窗口大小3.22.绘制地图…

记录好用的python包

记录好用的python包 PipxCentos 安装pipx确保 Pip 被安装更新 Pip安装 Pipx添加 Pipx 到 PATH临时添加到 PATH:永久添加到 PATH: 验证 Pipx 安装 Hatch安装特性 Poetry安装准备工作创建虚拟环境激活虚拟环境安装包追踪 & 更新包常用配置pycharm 远程连接poetry创建的虚拟环…

pycharm创建的项目

pycharm生成django templates删出 settings.py

数据分析_商品维度占比及变化可视化分析(Pandas和Matplotlib)

数据分析_商品维度占比及变化可视化分析(Pandas和Matplotlib) 分析维度包括: 各商品年度销量占比 各商品月度销量变化 构建测试数据 这里你可以了解到: 如何生成时间相关的数据。 如何从列表&#xff08;可迭代对象&#xff09;中生成随机数据。 Pandas 的 DataFrame 自…

IOS 32位调试环境搭建

一、背景 调试IOS程序经常使用gdb&#xff0c;目前gdb只支持32位程序调试&#xff0c;暂不支持IOS 64位程序调试。IOS 32位程序使用GDB调试之前&#xff0c;必须确保手机已越狱&#xff0c;否则无法安装和使用GDB调试软件。下面详细介绍GDB调试IOS 32位程序的环境搭建。 二、I…

数字时代的智慧演奏

数字化时代&#xff0c;工业不再是孤独的机器运转&#xff0c;而是演绎着一场智能与数据的华丽交响。无数智能节点的联动&#xff0c;数据的涌动&#xff0c;成为工业的新活力&#xff0c;同时也是创新的源泉。 工业互联网将每个机器、设备连接在一起&#xff0c;打破了原本独立…

从预训练损失的角度,理解语言模型的涌现能力

原文&#xff1a;Understanding Emergent Abilities of Language Models from the Loss Perspective 摘要 本文从预训练损失的角度重新审视语言模型的涌现能力&#xff0c;挑战了以往以模型大小或训练计算量为标准的观念。通过实验&#xff0c;作者发现预训练损失是预测下游任…

SRIO系列-时钟逻辑与复位逻辑

一、前言 上一篇讲述了SRIO协议的基本概念&#xff0c;传输的HELLO帧格式、事务类型等&#xff0c;本篇说一下SRIO IP核的时钟关系。 基本的IP设置可以参考此篇文章&#xff1a;【高速接口-RapidIO】Xilinx SRIO IP 核详解-CSDN博客 二、时钟关系 PHY可以在两个时钟域上运行…

C#语法知识之运算符

3、运算符 目录 3、运算符1、算数运算符思考 秒转化时间 2、字符串拼接3、条件运算符4、逻辑运算符5、位运算符6、三目运算符思考 闰年 1、算数运算符 1、赋值符号 //把右侧的值赋给左侧的变量2、算数运算符 _ * / float f 1 / 2f; %3、算数运算符的优先级 //乘除余优先级高…

【数据结构3-栈和队列】

数据结构3-栈和队列 1 栈-特殊的线性表-先进后出1.1 栈的三个案例 2 队列-与栈相反-先进先出2.1 队列的案例 3 用C实现栈的代码&#xff1a;4 用C实现队列的代码 1 栈-特殊的线性表-先进后出 1.1 栈的三个案例 2 队列-与栈相反-先进先出 2.1 队列的案例 3 用C实现栈的代码&…

<计算机网络自顶向下> TCP拥塞

目录 TCP拥塞控制机制 TCP拥塞感知 TCP速率控制方法 TCP拥塞控制和流量控制的联合动作 TCP拥塞控制策略 TCP吞吐量 TCP公平性 TCP拥塞控制机制 端到端的拥塞控制机制 路由器不向主机提供有关拥塞的反馈信息 路由器负担较轻 符合网络核心简单的TCP/IP架构原则 端系统根据自…

【机器学习】农田智能监控系统的实践探索

机器学习赋能现代农业&#xff1a;农田智能监控系统的实践探索 一、机器学习在现代农业中的重要作用二、机器学习在农田智能监控系统中的应用三、农田智能监控系统的实践意义 在科技飞速发展的今天&#xff0c;机器学习技术正以其强大的数据处理和模式识别能力&#xff0c;逐步…

Windows下Git的使用

目录 一、克隆远程仓库到本地二、git的三板斧2.1 add-将代码添加到本地仓库2.2 commit-提交代码到本地仓库2.3 push-推送本次添加操作到远程仓库2.4 gitee只有三板斧吗&#xff1f; 三、推送后没有出现绿点四、push到远程时报错五、git图形化界面下载链接 一、克隆远程仓库到本…

nodejs大文件上传

安装依赖 1.express 帮我们启动服务&#xff0c;并且提供接口 2.multer 读取文件&#xff0c;存储 3.cors 解决跨域 项目的目录结构&#xff1a; 前端代码&#xff1a; <input type"file" /><script>const file document.queryselector(input)// 分隔…

【漏洞复现】WordPress_Wholesale_Market admin-ajax.php 任意文件读取漏洞

0x01 产品简介 WordPress Wholesale Market是一个WordPress主题,专门设计用于创建批发市场和在线商城网站。该主题提供了许多功能和设计元素,使您能够轻松地构建一个功能强大的批发市场平台,以满足批发商和零售商的需求。 0x02 漏洞概述 WordPress Wholesale Market存在任…

(2022级)成都工业学院数据库原理及应用实验八: 数据库恢复技术

写在前面 1、基于2022级软件工程/计算机科学与技术实验指导书 2、成品仅提供参考 3、如果成品不满足你的要求&#xff0c;请寻求其他的途径 运行环境 window11家庭版 Navicat Premium 16 Mysql 8.0.36 实验要求 1、使用mysqldump实现数据库备份。 2、使用mysqldump实…

【声呐仿真】学习记录1-配置dave、uuv_simulator

【声呐仿真】学习记录1-配置dave、uuv_simulator 1.介绍2.配置3.一些场景 1.介绍 家|DAVE项目 — Home | Project DAVE 2.配置 参考官方教程安装|DAVE项目 — Installation | Project DAVE mkdir -p ~/uuv_ws/src cd ~/uuv_ws/src git clone https://github.com/Field-Robot…