【蓝桥杯】Python算法——求逆元的两种算法

news2025/1/19 14:24:18

目录

  • 零、前言
  • 一、逆元
  • 二、扩展欧几里得算法
  • 三、费马小定理
  • 四、总结

零、前言

距离25年蓝桥杯还有大概三个月时间,接下来重点应该会放在蓝桥杯备考方向,一起努力,一起加油


一、逆元

什么是逆元?这是数论中的一个基本概念。如果存在 a x ≡ 1 ( m o d   n ) ax\equiv1(mod \ n) ax1(mod n) x x x a a a在模 n n n意义下的逆元。可以简单地理解为,求一个 x x x使得 a x   m o d   n = 1 ax\ mod\ n=1 ax mod n=1
逆元的意义在哪呢?如果遇到需要求 a / b   m o d   n a/b\ mod\ n a/b mod n的情况,则可以转化为分子a乘以分母b的逆元的形式,这样我们将除法转化为乘法,提高了计算效率。


二、扩展欧几里得算法

那么怎么求解逆元呢?由前面给出的公式 a x ≡ 1 ( m o d   n ) ax\equiv1(mod \ n) ax1(mod n),不难看出求逆元 x x x就是求解等式的解: a x + n y = 1 ax + ny = 1 ax+ny=1因为 ( a x + n y )   m o d   n = a x   m o d   n (ax+ny)\ mod\ n = ax\ mod\ n (ax+ny) mod n=ax mod n,求出了 x x x y y y,那么 x x x就是 a a a的逆元。
为了方便推导,我们暂时把 n n n换成 b b b,等号右边换位 m m m,求解的更一般的形式。 a x + b y = m ax+by=m ax+by=m根据裴蜀定理:对于任意整数 a a a, b b b, m m m,求解未知整数 x x x, y y y时,必须满足 g c d ( a , b ) ∣ m gcd(a,b)|m gcd(a,b)m,即 m m m g c d ( a , b ) gcd(a,b) gcd(a,b)的倍数时才有解。
所以我们将计就计,如果 m m m g c d ( a , b ) gcd(a,b) gcd(a,b)的一倍,也就是 m = g c d ( a , b ) m = gcd(a,b) m=gcd(a,b),先解出方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的解 x 1 x_1 x1, y 1 y_1 y1,然后两边乘以 m / g c d ( a , b ) m/gcd(a,b) m/gcd(a,b),不就能求出来我们想要的了吗? a m x 1 g c d ( a , b ) + b m y 1 g c d ( a , b ) = m a\frac{mx_1}{gcd(a,b)}+b\frac{my_1}{gcd(a,b)}=m agcd(a,b)mx1+bgcd(a,b)my1=m所以,我们进一步研究问题:解出方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的解。
那么我们需要求出三个东西, x x x y y y g c d ( a , b ) gcd(a,b) gcd(a,b),这就是扩展欧几里得算法的根本研究问题。(By the way,欧几里得算法就是求解 g c d ( a , b ) gcd(a,b) gcd(a,b),方法就是我们熟知的辗转相除法。)
b = 0 b=0 b=0,有特解 x = 1 , y = 0 x=1,y = 0 x=1,y=0,这是迭代的初始条件。
b ≠ 0 b\neq0 b=0,假设 x 1 x_1 x1 y 1 y_1 y1 a x 1 + b y 1 = g c d ( a , b ) ax_1+by_1=gcd(a,b) ax1+by1=gcd(a,b)的解,根据欧几里得算法: g c d ( a , b ) = g c d ( b , a   m o d   b ) gcd(a,b) = gcd(b,a\ mod\ b) gcd(a,b)=gcd(b,a mod b),下一步我们构造 b x 2 + ( a   m o d   b ) y 2 = g c d ( b , a   m o d   b ) bx_2+(a\ mod\ b)y_2 = gcd(b, a\ mod\ b) bx2+(a mod b)y2=gcd(b,a mod b),
a   m o d   b a\ mod\ b a mod b怎么表示?不就是 a / b a/b a/b的余数嘛,所以你细品:a%b = a - (a//b)*b,( a ÷ b = q … … r a \div b = q……r a÷b=q……r,则 a = b ∗ q + r a = b*q + r a=bq+r,其中q就是a整除b的结果a//b), 带入到上式则有 b x 2 + ( a   m o d   b ) y 2 = b x 2 + ( a − ( a / / b ) b ) y 2 = g c d ( b , a   m o d   b ) bx_2+(a\ mod\ b)y_2 = bx_2+(a - (a//b)b)y_2 = gcd(b,a\ mod\ b) bx2+(a mod b)y2=bx2+(a(a//b)b)y2=gcd(b,a mod b)
好乱,整理一下:
{ a x 1 + b y 1 = g c d ( a , b ) b x 2 + ( a − ( a / / b ) b ) y 2 = g c d ( b , a   m o d   b ) g c d ( a , b ) = g c d ( b , a   m o d   b ) \left\{ \begin{aligned} ax_1 + by_1 &= gcd(a,b) \\ bx_2+(a - (a//b)b)y_2 &= gcd(b,a\ mod\ b) \\ gcd(a,b) &= gcd(b,a\ mod\ b) \end{aligned} \right. ax1+by1bx2+(a(a//b)b)y2gcd(a,b)=gcd(a,b)=gcd(b,a mod b)=gcd(b,a mod b)这样我们就能找到 ( x 1 , y 1 ) (x_1,y_1) (x1,y1) ( x 2 , y 2 ) (x_2,y_2) (x2,y2)的关系了: a x 1 + b y 1 = a y 2 + b ( x 2 − ( a / / b ) y 2 ) ax_1+by_1 = ay_2 + b(x_2 - (a//b)y_2) ax1+by1=ay2+b(x2(a//b)y2),所以有 { x 1 = y 2 y 1 = x 2 − ( a / / b ) y 2 \left\{ \begin{aligned} x_1 &= y_2\\ y_1 &= x_2 - (a//b)y_2 \end{aligned} \right. {x1y1=y2=x2(a//b)y2这就是递归的关系式。
有了初始值与递归关系,就可以写代码来求解了。

def exgcd(a,b):
	if b==0:
		return a,1,0
	gcd,x2,y2 = exgcd(b,a%b)
	x1,y1 = y2,x2-(a//b)*y2
	return gcd,x1,y1

别忘了我们求的是 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b),而我们要求的是 a x + b y = m ax+by=m ax+by=m,那么对于函数输出,还要再乘以 m / g c d m/gcd m/gcd

def Func(a,b,m):
	gcd,x1,y1 = exgcd(a,b)
	if m % gcd != 0:return None,None,None
	x0, y0 = x * m // gcd, y * m // gcd
	return gcd, x0, y0

汇总:

def exgcd(a,b):
	if b==0:
		return a,1,0
	gcd,x2,y2 = exgcd(b,a%b)
	x1,y1 = y2,x2-(a//b)*y2
	return gcd,x1,y1
	
def Func(a,b,m):
	gcd,x1,y1 = exgcd(a,b)
	if m % gcd != 0:return None,None,None
	x0, y0 = x * m // gcd, y * m // gcd
	return gcd, x0, y0

MOD = 1e9+7
a = int(input())
_, inv_a, _ = Func(a, MOD, 1)
print(inv_a)

三、费马小定理

费马小定理
如果 p p p是素数,且 a a a是一个不能被 p p p整除的整数,那么: a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv1({\mathrm{mod}}p) ap11(modp)

这给了我们一个求逆元的好方法: a a p − 2 ≡ 1 ( m o d   p ) aa^{p-2}\equiv1(mod\ p) aap21(mod p)注意前提:模数为素数,且 a a a不能被 p p p整除。
这时我们只需要算一下 a p − 2 a^{p-2} ap2就行了,很方便吧。可以用快速幂来求。

def KSM(a, b, mod):
	if b == 0: return 1
	if b == 1: return a % mod
	res = KSM(a, b//2, mod)
	res = res * res % mod
	if b % 2 == 1:
		res = res * a % mod
	return res

def INV(a):
	return KSM(a, MOD-2, MOD)

MOD = 1e9+7
a = int(input())
print(INV(a))

四、总结

介绍了两种方法求解逆元:扩展欧几里得算法和费马小定理算法,前者实用性广,而后者有一个前提,即模数必须为素数,不过一般用费马小定理的情况要多一些。

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

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

相关文章

Kibana 控制台中提供语义、向量和混合搜索

作者:来自 Elastic Mark_Laney 想要将常规 Elasticsearch 查询与新的 AI 搜索功能结合起来吗?那么,你不需要连接到某个第三方的大型语言模型(LLM)吗?不。你可以使用 Elastic 的 ELSER 模型来改进现有搜索&a…

多种 Docker 镜像拉取解决方案与实践

最近国内 Docker 镜像拉取不太通畅,尝试了几种镜像拉取的方式,写篇博客分享一下。 原以为只是 docker hub 被毙了,上机器一操作,官方的下载地址也被毙了,真是从源头解决问题。 不过还好目前还有其他源能用&#xff0…

2025边缘计算新年沙龙成功举办,共话边缘AI未来

1月11日下午,北京市海淀区中关村创业大街热闹非凡,以“云边腾跃,蛇启新航”为主题的 2025边缘计算新年沙龙 盛大举行。本次活动汇聚了边缘计算、人工智能以及云边协同领域的顶尖专家、学者和从业者,共同探讨技术前沿与实际应用场景…

使用redis-cli命令实现redis crud操作

项目场景: 线上环境上redis中的key影响数据展示,需要删除。但环境特殊没办法通过 redis客户端工具直连。只能使用redis-cli命令来实现。 操作步骤: 1、确定redis安装的服务器; 2、找到redis的安装目录下 ##找到redis安装目…

CentOS 下载软件时报Error: Failed to synchronize cache for repo ‘AppStream‘解决方法

下载软件时出现以下问题 直接把CentOS-AppStream.repo改个名字就行 cd /etc/yum.repos.d/ mv CentOS-AppStream.repo CentOS-AppStream.repo.bak就可以了 解决思路 把AI问遍,无人会,解决法 想要下载软件通通失败了,解决方法当然是问AI&am…

【深度学习】神经网络之Softmax

Softmax 函数是神经网络中常用的一种激活函数,尤其在分类问题中广泛应用。它将一个实数向量转换为概率分布,使得每个输出值都位于 [0, 1] 之间,并且所有输出值的和为 1。这样,Softmax 可以用来表示各类别的预测概率。 Softmax 函…

python管理工具:conda部署+使用

python管理工具:conda部署使用 一、安装部署 1、 下载 - 官网下载: https://repo.anaconda.com/archive/index.html - wget方式: wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh2、 安装 在conda文件的…

当PHP遇上区块链:一场奇妙的技术之旅

PHP 与区块链的邂逅 在技术的广袤宇宙中,区块链技术如同一颗耀眼的新星,以其去中心化、不可篡改、透明等特性,掀起了一场席卷全球的变革浪潮。众多开发者怀揣着对新技术的热忱与探索精神,纷纷投身于区块链开发的领域,试…

unity——Preject3——开始界面拼面板

目录 1.创建panel,去掉panel自带的image,自己加一个image,使用锚点分配好 2.锚点(快捷键点击后 ALTShift) 锚点是什么? 锚点的实际例子 例子1:固定在父容器的中心 例子2:对齐到…

PyTorch使用教程(6)一文讲清楚torch.nn和torch.nn.functional的区别

torch.nn 和 torch.nn.functional 在 PyTorch 中都是用于构建神经网络的重要组件,但它们在设计理念、使用方式和功能上存在一些显著的区别。以下是关于这两个模块的详细区别: 1. 继承方式与结构 torch.nn torch.nn 中的模块大多数是通过继承 torch.nn…

传统以太网问题与VLAN技术详解

传统以太网的问题 广播域:在网络中能接收同一广播信息的所有设备(计算机、交换机)等的集合 说明:在一个广播域内,当一个设备发送广播帧时,该域内的所有设备都能接收到这个广播帧。工作原理:在以…

OpenAI Whisper:语音识别技术的革新者—深入架构与参数

当下语音识别技术正以前所未有的速度发展,极大地推动了人机交互的便利性和效率。OpenAI的Whisper系统无疑是这一领域的佼佼者,它凭借其卓越的性能、广泛的适用性和创新的技术架构,正在重新定义语音转文本技术的规则。今天我们一起了解一下Whi…

WPS计算机二级•高效操作技巧

听说这里是目录哦 斜线表头 展示项目名称🍋‍🟩横排转竖排🍐批量删除表格空白行🍈方法一方法二建辅助列找空值 能量站😚 斜线表头 展示项目名称🍋‍🟩 选中单元格,单击右键➡️“设…

RabbitMQ实现延迟消息发送——实战篇

在项目中,我们经常需要使用消息队列来实现延迟任务,本篇文章就向各位介绍使用RabbitMQ如何实现延迟消息发送,由于是实战篇,所以不会讲太多理论的知识,还不太理解的可以先看看MQ的延迟消息的一个实现原理再来看这篇文章…

《Keras 3 在 TPU 上的肺炎分类》

Keras 3 在 TPU 上的肺炎分类 作者:Amy MiHyun Jang创建日期:2020/07/28最后修改时间:2024/02/12描述:TPU 上的医学图像分类。 (i) 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 简介 设置 本教程将介…

1.17组会汇报

STRUC-BENCH: Are Large Language Models Good at Generating Complex Structured Tabular Data? STRUC-BENCH:大型语言模型擅长生成复杂的结构化表格数据吗?23年arXiv.org 1概括 这篇论文旨在评估大型语言模型(LLMs)在生成结构…

PyTorch使用教程(2)-torch包

1、简介 torch包是PyTorch框架最外层的包,主要是包含了张量的创建和基本操作、随机数生成器、序列化、局部梯度操作的上下文管理器等等,内容很多。我们基础学习的时候,只有关注张量的创建、序列化,随机数、张量的数学数学计算等常…

idea gradle compiler error: package xxx does not exist

idea 编译运行task时报项目内的包不存在,如果你试了网上的其它方法还不能解决,应该是你更新了新版idea,项目用的是旧版jdk,请在以下编译器设置中把项目JDK字节码版本设为8(jdk1.8,我这里是17请自行选择&…

Nmap之企业漏洞扫描(Enterprise Vulnerability Scanning for Nmap)

简介 Namp是一个开源的网络连接端扫描软件,主要用于网络发现和安全审核。‌它可以帮助用户识别网络上的设备、分析它们的服务、检测操作系统类型,甚至发现潜在的安全漏洞。Nmap由Fyodor开发,最初是为了满足网络管理员的需求,但随…

RabbitMQ前置概念

文章目录 1.AMQP协议是什么?2.rabbitmq端口介绍3.消息队列的作用和使用场景4.rabbitmq工作原理5.整体架构核心概念6.使用7.消费者消息推送限制(work模型)8.fanout交换机9.Direct交换机10.Topic交换机(推荐)11.声明队列…