蓝桥杯基础数论(Python组)

素数 & 约数 & 幂 & 阶乘

一、素数

素数又称质数,一个大于1且只能被1和它本身整除的数被称为素数。对素数的求解往往是解决素数和约数问题的基础。

(1)求解方法

素数的求解有试除法、埃氏筛和线性筛三种求法,其中线性筛效率最高,此处只列出线性筛代码,因为线性筛不仅效率高,还可以方便地求出每个数的最小质因数,用途更广。
注意在考试的时候尽量打表,蓝桥杯的内存限制比较宽,一般不会出现内存溢出。不要让素数的搜索占用宝贵的程序运行时间。

# 线性筛
def sieve(n):# find out all of the prime numbers between 2 and nprime = []is_prime = [True]*(n+1)for i in range(2,n+1):if is_prime[i]:prime.append(i)for j in prime:# 注意这三个操作的顺序不可调换if i*j > n:breakis_prime[i*j] = Falseif i%j == 0:# 只用最小的质因数筛除非质数,减少了重复的运算# 因为j已经筛过一遍了,所以不需要用i重复筛了break           return prime

只需要对线性筛算法中筛除非质数的部分进行修改,在筛除某个值的同时记录筛除它的数即可

def sieve(n):prime = []is_prime = [True]*(n+1)min_prime = [1]*(n+1)for i in range(2,n+1):if is_prime[i]:prime.append(i)# 素数的最小质因子是它本身min_prime[i] = ifor j in prime:if i*j > n:breakis_prime[i*j] = False# 在排除数字i*j的同时记录它的最小质因子j# 注意此处i不一定是质数min_prime[i*j] = jif i%j == 0:breakreturn min_prime

(2)求最小质因数

对于一个给定正整数,只需要从2开始逐个试除,第一个能够整除n的数就是其最小质因数。这个方法可以用反证法证明,如果第一个整除n的数是一个合数,那么n也一定可以被这个合数的每一个因数所整除,又因为合数存在小于其本身的因数,所以这个合数一定不是第一个能够整除n的数,这与假设矛盾,故原结论得证。

n = int(input())
for i in range(2,n+1):if n%i == 0:print(i)break

(3)例题演示

例题:分解质因数
题目描述:

求出区间[a,b]中所有整数的质因数分解。

输入:

输入一行,包含两个用空格分割的正整数,分别表示 a 和 b。

输出:

每行输出一个数的分解,形如 k = a 1 ∗ a 2 ∗ a 3... k=a1* a2 *a3... k=a1a2a3... (a1<=a2<=a3…,k也是从小到大的)

# BF做法:直接对每一个在区间[a,b]内的数从2开始试除,但由于时间复杂度过高,一定会超时
# firstly,find out all the prime number that are smaller than n+1
def sieve(n):prime = []is_prime = [True]*(n+1)for i in range(2,n+1):if is_prime[i]:prime.append(i)for j in prime:if i*j > n:breakis_prime[i*j] = Falseif i%j == 0:breakreturn prime
# main part
a,b = map(int,input().split())
prime = sieve(b)
# divide every number in the interval
for i in range(a, b+1):print(f'{i} = ', end = '')# create a string to store the result of divisionline = [] for j in prime:if i == 1:breakwhile i%j == 0:line.append(str(j))line.append('*')i //= j# print the result of divisionline.pop(-1)print(''.join(line))

二、约数

约数又称因数,整数a除以非零整数b,除得的商正好是整数,余数为0,就说a能够被b整除,a是b的倍数,b是a的约数。

(1)求约数个数

约数个数定理:

对任意一个大于1的正整数 X X X 都可以表示为若干个质数乘积的格式,即 X = P 1 a 1 ∗ P 2 a 2 ∗ . . . ∗ P k a k X = P_1^{a_1} * P_2^{a_2} * ... * P_k^{a_k} X=P1a1P2a2...Pkak,则约数的个数就是 ( a 1 + 1 ) ∗ ( a 2 + 1 ) ∗ . . . ∗ ( a k + 1 ) (a_1 + 1)*(a_2 + 1)*...*(a_k + 1) (a1+1)(a2+1)...(ak+1),注意这个结果中的约数包含1。

from collections import defaultdict
# calculate out the prime numbers that smaller than the given number
def sieve(n):prime = []is_prime = [True]*(n+1)for i in range(2, n+1):if is_prime[i]:prime.append(i)for j in prime:if i*j > n:breakis_prime[i*j] = Falseif i%j == 0:breakreturn prime
n = int(input())
prime = sieve(n)
# divide the given number by these prime numbers
# use a defaultdict to record the times that every number appear in the given number
d = defaultdict(int) 
for i in prime:while n%i == 0:d[i] += 1n //= i
# use the data to figure out the answer
ans = 1
for i in d.values():ans *= (i+1)
print(ans)

(2)求所有的约数

求约数的个数主要还是使用试除法,因为先计算所有质因数然后组合的时间复杂度过高,但也应注意到可以使用适当的优化提升算法的效率。

# BF algorithm
n = int(input())
res = []
for i in range(1, n+1):if i > (n//i):# all of the numbers that bigger than this value have alreadly been recordedbreakif n%i == 0:res.append(i)n //= i# record the number that left as wellif n != i:res.append(n)
res.sort()
print(res)

(3)最大公因数

求两个数的最大公因数的方法有辗转相除法和更相减损术等,此处只介绍应用范围更广且时间复杂度更小的辗转相除法。辗转相除法,又名欧几里得算法,是一种可以利用递归或递推快速求除出两数最大公因数的算法,时间复杂度为 O ( l o g n ) O(logn) O(logn)

# 欧几里得算法
def gcd(a,b):if b == 0:return areturn gcd(b,a%b)

欧几里得算法既可以在考场时自己实现,也可以直接调用python的math标准库中的gcd()函数。

from math import gcd
m = 10
n = 6
print(gcd(m,n)) # output:2

(4)最小公倍数

求解定理:

最小公倍数 = 两数之积 // 最大公因数

from math import gcd
def gbs(a,b):return a*b//gcd(a,b)

三、幂

幂的运算可以使用python的运算符**实现,也可以自行建立快速幂函数。快速幂算法的时间复杂度是 O ( l o g n ) O(logn) O(logn)

def qpow(a,n):if n == 0:return 1res = 1while n:if n&1:# n is an odd numberres = res * an >>= 1 # n need to be divided by 2a = a * a return res

四、阶乘

阶乘是蓝桥杯的高频考点,基本上每年都有一道题,大部分是简单填空题,但大题还是比较难的,
主要需要注意其递推特性( n ! = n ∗ ( n − 1 ) ! n! = n*(n-1)! n!=n(n1)!)和n与约数之间的关系。这里列出两道题目,分别涵盖以上两个难点。

例题 1:求阶乘(蓝桥杯第13届省赛真题)

题目描述:

满足 N ! N! N! 的末尾恰好有 K K K 个0的最小的 N N N 是多少?输出这个数。如果这样的 N N N 不存在,输出-1

输入格式:

输入一行,包含一个整数,表示k

输出格式:

输出一行,包含一个整数

提示:

对于 30 % 30\% 30% 的数据, 1 ≤ K ≤ 1 0 6 1 \leq K \leq 10^6 1K106,
对于 100 % 100\% 100% 的数据, 1 ≤ K ≤ 1 0 18 1 \leq K \leq 10^{18} 1K1018

代码示例:

# 暴力做法,只能通过40%的样例
# 0只能通过乘以10的倍数或5的倍数获得,因为2的倍数远多于5的倍数,所以不用考虑
# 100,1200之类的数需要特别处理
from sys import exitk = int(input())
if k < 0:print(-1)exit()
# 从5开始,以5为步长搜索5的倍数和10的倍数
n = 0 # 记录当前遍历到的因数
cur = 0 # 记录当前所得到的0的个数
while cur < k:n += 5# 先将n末尾所有的0转移到cur上temp = nwhile temp%10 == 0:temp //= 10cur += 1# 然后统计temp中5的个数while temp%5 == 0:temp //= 5cur += 1
if cur == k:print(n)
else:print(-1)

注意到对于一个给定的 n ! n! n!,末尾0的个数 = 从1到n各个数字的约数中5的个数 = k
k = n 5 1 + n 5 2 + n 5 3 + . . . k = \frac n {5^1} + \frac n {5^2} + \frac n {5^3} + ... k=51n+52n+53n+... 可以高效地求出指定n!的末尾0个数,所以可以使用二分法提高查找效率。

# Binary Search Optimize
# 注意到末尾0的个数随n的增大只会增大,不会减小,且结果的末尾0个数有大于等于k和小于k两种状态,所以可以使用二分法高效求解
def check(n):# 求出 n! 末尾0的个数res = 0# 这个过程的实质是求出构成阶乘的数字中所有5的倍数,25的倍数,125的倍数...while n:n //= 5res += nreturn res# binary search main part
k = int(input())
left = 1
right = 10**19
while left < right:mid = (left+right)//2if check(mid) < k:left = mid+1else:# mid 可能是正确答案,所以不能舍弃right = mid
# left = right
if check(left) == k:# 存在解print(left)
else:print(-1)

例题 2:阶乘的和(蓝桥杯第14届省赛真题)

题目描述:

给定 n 个数 A i A_i Ai,问能满足 m! 为 ∑ i = 1 n ( A i ! ) ∑_{i=1}^n(A_i!) i=1n(Ai!) 的因数的最大的 m 是多少。其中 m! 表示 m 的阶乘,即 1 × 2 × 3 × ⋅ ⋅ ⋅ × m 1 × 2 × 3 × · · · × m 1×2×3×⋅⋅⋅×m

输入格式:

输入的第一行包含一个整数 n 。
第二行包含 n 个整数,分别表示 A i A_i Ai,相邻整数之间使用一个空格分隔。

输出格式:

输出一行包含一个整数表示答案。

提示:

对于 40 % 40\% 40% 的评测用例, n ≤ 5000 n ≤ 5000 n5000
对于所有评测用例, 1 ≤ n ≤ 1 0 5 , 1 ≤ A i ≤ 1 0 9 1 ≤ n ≤ 10^5,1 ≤ A_i ≤ 10^9 1n105,1Ai109

解题思路:
在极限情况下,a数组中各个值均只出现一次,各阶乘无法合并,那么m! = a[0]!,a[0] = min(a)
本题中各个a[i]可能重复出现,因此存在合并阶乘的可能(比如n!*(n+1) = (n+1)!),所以m! = min(s)
s是合并化简后的a数组各元素阶乘和式子中阶乘元素的集合
通过以上分析可知m!应当是分子中各个阶乘合并后最小的阶乘
通过分治求出合并后的最小阶乘
temp = (x*a[0] + y*(a[0]+1)),x,y分别是a[0],a[0]+1在a中的个数
显然a[0]<=m,现在要看合并结果是否是a[0]+1的倍数,(a[0]+1)*y显然是(a[0]+1)的倍数

倍数性质:m的倍数+不是m倍数的数,则结果一定不是m的倍数

由倍数定律可知如果x*a[0]是(a[0]+1)的倍数,则temp就是(a[0]+1)的倍数
又因为gcd(a[0],a[0]+1) = 1,所以‘x*a[0]是(a[0]+1)的倍数’等价于x是(a[0]+1)的倍数

n = int(input())
a = sorted([int(i) for i in input().split()])
# 从最小的a[0]开始递推
# 创建一个变量记录当前阶乘的系数
k = 1
# 创建一个变量记录当前阶乘的值
cur = a[0]
for i in range(1,n):if cur == a[i]:k += 1else:# cur < a[i]# 检查系数是否能够合并进当前阶乘中while k%(cur+1) == 0 and k//(cur+1) != 0:cur += 1k //= curif cur == a[i] :break# 无法达到a[i]if cur < a[i]:breakelse:# 成功到达a[i]k += 1
print(cur)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

xbackup 备份MySQL数据库脚本

#!/bin/bash ## 方法一:将回车符(\r)替换为换行符(\n) 替换不可见字符 报错问题:shell脚本执行错误 $‘\r‘:command not found ## sed -i s/\r// xtrabackup.sh ## 备份计划任务 ## ## 每天凌晨1:30一次全量备份 ## 每天间隔1小时一次增量备份 ## 30 1 * * * backup…

2024年新算法!PCA+CPO+K-means聚类,冠豪猪优化器(CPO)优化K-means,适合学习,也适合发paper

2024年新算法&#xff01;PCACPOK-means聚类&#xff0c;冠豪猪优化器&#xff08;CPO)优化K-means&#xff0c;适合学习&#xff0c;也适合发paper。 一、冠豪猪优化器 摘要&#xff1a;受冠豪猪(crest Porcupine, CP)的各种防御行为启发&#xff0c;提出了一种新的基于自然…

如何在Flutter中实现一键登录

获取到当前手机使用的手机卡号&#xff0c;直接使用这个号码进行注册、登录&#xff0c;这就是一键登录。 可以借助极光官方的极光认证实现 1、注册账户成为开发者 2、创建应用开通极光认证 &#xff08;注意开通极光认证要通过实名审核&#xff09; 3、创建应用获取appkey、 …

KeyguardViewMediator的面试题目

以下是一些关于KeyguardViewMediator的面试题目及简要答案&#xff1a; 题目&#xff1a;简述KeyguardViewMediator在Android系统中的作用。 答案&#xff1a;KeyguardViewMediator是Android系统中管理锁屏界面&#xff08;Keyguard&#xff09;的核心组件&#xff0c;它协调锁…

【C语言】结构体与位段

一、前言 我们之前学习过定义一个整型类型的变量又或者定义一个浮点型类型的变量...&#xff0c;这些变量可以描述一个整数又或者描述一个小数...&#xff0c;可无论是整数还是小数...&#xff0c;它们也只是简单对象。如果我们想要描述像一本书&#xff0c;一个人这种复杂对象…

域名系统

▶1.域名系统 数字式IP地址(如210.43.206.103)难以记忆&#xff0c;如果使用易于记忆的符号地址(如www.csust.cn)来表示&#xff0c;就可以大大减轻用户的负担。这就需要一个数字地址与符号地址相互转换的机制&#xff0c;这就是因特网域名系统(DNS)。 域名系统(DNS)是分布在因…

【算法与数据结构】深入二叉树实现超详解

文章目录 &#x1f4dd;前言&#x1f320; 接口函数✏️ 实现函数&#x1f309;创建树的新节点&#x1f320;通过前序遍历的数组构建二叉树&#x1f309;包装通过前序遍历的数组构建二叉树&#x1f320;二叉树的销毁&#x1f320;层次遍历&#x1f320;第一种实现&#xff1a;不…

Android: Gradle 命令

一、查看整个项目依赖传递关系 x.x.x (*) 该依赖已经有了&#xff0c;将不再重复依赖。x.x.x -> x.x.x 该依赖的版本被箭头所指的版本代替。x.x.x -> x.x.x(*) 该依赖的版本被箭头所指的版本代替&#xff0c;并且该依赖已经有了&#xff0c;不再重复依赖。 1. gradlew ap…

Python实战:枚举类型enum及应用

1. 引言 在编程中&#xff0c;我们经常需要定义一组具有特定意义的常量。在Python中&#xff0c;可以使用枚举类型&#xff08;enum&#xff09;来实现这一功能。枚举类型提供了一种方便、安全的方式来管理一组相关的常量。通过使用枚举类型&#xff0c;我们可以避免使用魔法数…

002 高并发内存池_定长内存池设计

​&#x1f308;个人主页&#xff1a;Fan_558 &#x1f525; 系列专栏&#xff1a;高并发内存池 &#x1f339;关注我&#x1f4aa;&#x1f3fb;带你学更多知识 文章目录 前言一、设计整体框架二、New操作&#xff08;申请空间&#xff09;三、Delete操作&#xff08;用自由链…

Redis 教程系列之Redis 数据类型(四)

Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。 String(字符串) string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。 string 类型是…

B3626 跳跃机器人

题目描述 地上有一排格子&#xff0c;共 n 个位置。机器猫站在第一个格子上&#xff0c;需要取第 n 个格子里的东西。 机器猫当然不愿意自己跑过去&#xff0c;所以机器猫从口袋里掏出了一个机器人&#xff01;这个机器人的行动遵循下面的规则&#xff1a; 初始时&#xff0…

奇舞周刊第523期:来自 rust 生态的强烈冲击?谈谈 Leptos 在语法设计上的精妙之处...

奇舞推荐 ■ ■ ■ 来自 rust 生态的强烈冲击&#xff1f;谈谈 Leptos 在语法设计上的精妙之处 过去很长一段时间&#xff0c;前端框架们都在往响应式的方向发展。同时又由于 React hooks 的深远影响&#xff0c;函数式 响应式成为了不少前端心中最理想的前端框架模样。Solid …

设计模式-初步认识

目录 &#x1f6fb;1.什么是设计模式 &#x1f69a;2.设计模式的优点 &#x1f68d;3.设计模式6大原则 &#x1f6f4;4.设计模式类型 1.什么是设计模式 设计模式代表了最佳的实践&#xff0c;通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开…

Yocto学习笔记1-下载与首次编译

Yocto学习笔记1-下载与首次编译 1、基础环境介绍2、注意点3、安装依赖3.1 yocto常规系统构建所需依赖库&#xff08;较全&#xff09;3.2 龙芯适配时的最小依赖库&#xff08;最小&#xff09; 4、下载4.1 通过git克隆4.2 查看所有远程分支4.3 签出一个长期支持的稳定版本4.4 查…

vue3中ref详解

在Vue 3中&#xff0c;ref是一个核心功能&#xff0c;它允许我们创建响应式引用&#xff0c;这对于处理基本类型数据&#xff08;如字符串、数字等&#xff09;特别有用。ref通过Vue的响应式系统&#xff0c;确保当数据变化时&#xff0c;相关的视图会自动更新。下面将结合代码…

从边缘设备丰富你的 Elasticsearch 文档

作者&#xff1a;David Pilato 我们在之前的文章中已经了解了如何丰富 Elasticsearch 本身和 Logstash 中的数据。 但如果我们可以从边缘设备中做到这一点呢&#xff1f; 这将减少 Elasticsearch 要做的工作。 让我们看看如何从具有代理处理器的 Elastic 代理中执行此操作。 E…

有向图的BFS(c++题解)

题目描述 给定一个有向图&#xff0c;有N个顶点&#xff0c;M条边&#xff0c;顶点从1..N依次编号&#xff0c;求出字典序最小的宽度优先搜索顺序。 输入格式 第1行&#xff1a;2个整数&#xff0c;N&#xff08;1≤N≤200&#xff09;和M&#xff08;2≤M≤5000&#xff09…

Redis如何删除大key

参考阿里云Redis规范 查找大key&#xff1a; redis-cli --bigkeys 1、String类型&#xff1a; Redis 4.0及以后版本提供了UNLINK命令&#xff0c;该命令与DEL命令类似&#xff0c;但它会在后台异步删除key&#xff0c;不会阻塞当前客户端&#xff0c;也不会阻塞Redis服务器的…

【漏洞复现】WordPress Plugin NotificationX 存在sql注入CVE-2024-1698

漏洞描述 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 WordPress Plugin NotificationX 存在安全漏洞,该漏洞源于对用户提供的…