欧几里得与扩展欧几里得算法(含推导过程及代码)

news2024/9/21 8:00:40

文章目录

  • 前言
  • 一、欧几里得算法
  • 二、扩展欧几里得算法
    • 2.1、认识裴蜀定理
    • 2.2、推导ax+by=gcd(a, b)得到x与y
      • 2.2.1、推导过程
      • 2.2.2、代码实现
    • 2.3、推导ax+by=gcd(a, b)的所有解及a或者b的最小值(结论+验证)
  • 参考文章

前言

在学习Acwing c++蓝桥杯辅导课第八讲数论-AcWing 1299. 五指山时有使用到扩展欧几里得算法,这里来记录下知识点。

当前文章已收录到博客文件目录索引:博客目录索引(持续更新)

一、欧几里得算法

介绍

欧几里得算法:欧几里得算法又称辗转相除法,用于计算两个整数a,b的最大公约数。

  • gcd(a, b) = d,该d就是最大公约数。

代码

class Solution {

    //欧几里得算法(辗转相除法)
    public static int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    public static void main(String[] args) {
        System.out.println(gcd(12, 5));
    }
}

二、扩展欧几里得算法

2.1、认识裴蜀定理

裴蜀定理,又称贝祖定理(扩展欧几里得):说明了对任何整数a、b和它们的最大公约数d,关于未知数x和y的线性不定方程(称为裴蜀等式),是一个关于最大公约数的定理。

若是a,b是整数,且gcd(a, b) = d,那么一定存在整数x,y,使ax+by=d成立。

2.2、推导ax+by=gcd(a, b)得到x与y

2.2.1、推导过程

针对于方程:ax+by=gcd(a, b)

①当b = 0时,ax + by = a,则x = 1, y = 0。【实际上就是求解到最大公约数临界时】

②当b ≠ 0时,即gcd(a, b) = gcd(b, a % b),根据裴蜀定理gcd(a, b) = d => ax+by=d

gcd(b, a % b) = bx’ + (a % b)y’ ,又a % b = a - (int)(a / b) * b,其中这个a/b是得到整数,即a % b = a - a/b*b

gcd(b, a % b) = bx’ + (a - a/b*b)y’,接着来进行拆解式子为ay’ + b(x’ - (a/b) * y)

此时得到式子:gcd(b, a % b) = ay’ + b(x’ - (a/b) * y’)

又gcd(a, b) = ax + by,又gcd(a, b) = gcd(b, a % b)

此时ax + by = ay’ + b(x’ - (a/b) * y’)

  • x = y’
  • y = x’ - (a/b) * y’

这个y’,x’指的是当前递归层级时的x,y。

2.2.2、代码实现

class Solution {

    /**
     * x.a + b * y = d
     * @param a
     * @param b
     * @param arr 存储x,y
     */
    public static int exGcd(int a, int b, int[] arr) {
        if (b == 0) {
            //此时已经求得最大公约数即为a,此时默认x为1,y为0
            arr[0] = 1;
            arr[1] = 0;
            return a;
        }
        //递归求得最大公约数
        int d = exGcd(b, a % b, arr);
        //通过公式去化解转为 x = y',y = x‘ - a/b*y'
        int temp = arr[0];
        arr[0] = arr[1];
        arr[1] = temp - a / b * arr[1];
        return d;
    }

    public static void main(String[] args) {
        //扩展欧几里得计算得到x,y
        int[] arr = new int[2];
        System.out.printf("最大公约数为:%d\n", exGcd(12, 5, arr));
        System.out.printf("x = %d, y = %d", arr[0], arr[1]);
    }
}

image-20230124164526480


2.3、推导ax+by=gcd(a, b)的所有解及a或者b的最小值(结论+验证)

利用扩展欧几里得算法我们可以去推导ax+by=gcd(a, b),从而得到一组x与y的解。

结论

通过这么一组x与y的解我们可以得到所有的x与y解

这里我们将gcd(a,b)来用d表示,ax+by = d。

定义:a’ = a d \frac{a}{d} da,b‘ = b d \frac{b}{d} db

x与y公式定义结论:所有的x,y解为

x = x0 + kb'
y = y0 - ka'

x或者y最小正整数值结论(这里举y最小正整数值):y = y % a’,此时即可得到最小的y值。

  • 我们可以直接将第一组解的y代入或者使用求得的y0代入都是可以得到最小正整数解!

相关算法题目:AcWing 1299. 五指山

证明推导

①x与y公式定义结论推导

我们来尝试将x与y的最终推导公式带入到ax+by = d式子中:

ax+by = a(x0 + kb’) + b(y0 - ka’) = ax0 + akb’ + by0 - bka’ = ax0 + by0 + akb’ - bka’

此时我们将a’ = a d \frac{a}{d} da,b‘ = b d \frac{b}{d} db代入到akb’ - bka’中去,akb’ = ak.b / d,bka’ = bk.a / d,也就是说akb’ = bka’

所以ax0 + by0 + akb’ - bka’ = ax0 + by0 = d,得证!

我们来举例子证明下对应的a’与b’以及x与y通式是否正确:

给出a = 12,b = 5,d = gcd(a, b) = 1
根据扩展欧几里得可以得到式子:ax + by = d
	通过算法来得到一组x、y解,x = -2,y = 5      // 式子为:-2*12 + 5*5 = 1
接着我们根据①中的公式定理,a' = a / d,b' = b / d  //  a' = 12/1 = 12, b' = 5 / 1 = 5
对应x与y的所有解公式为:x = x0 + kb',y = y0 - ka'

此时我们可以去尝试得到x0的解(假设k=1)-2 = x0 + 1*5,得到x0 = -7
     尝试得到y0的解(假设k=1)5 = y0 - 1*12,得到y0 = 17
    
ok,此时x0 = -7,y0 = 17,我们来自己通过公式去尝试构造一组解,设置k = 2,
   	 x = -7 + 2 * 5 = 3
 	 y = 17 - 2 * 12 = -7
尝试代入ax+by=d中,即为12 * 3 + 5 * (-7) = 1,此时能够验证成功!

②y最小正整数值举例:y = y % a’

依旧使用①中的例子我们来求y的最小值:a = 12,b = 5,a’ = 12,b’ = 5,x0 = -7,y0 = 17

//使用y0代入
17 % 12 = 5
    
//使用y代入(第一组解得到的值y = 5)
5 % 12 = 5
    
//使用y为负数情况代入(自己设置k=2时得到的y解)
-7 % 12 = -5
//对于该特殊情况我们需要使用(y mod a' + a') % a'
(-7 % 12 + 12) % 12 = (-5 + 12) % 12 = 17 % 12 = 5

结论:我们可以直接将第一组解的y代入或者使用求得的y0代入都是可以得到最小正整数解!

参考文章

[1]. 扩展欧几里得算法 思想及模板代码

[2]. 扩展欧几里得算法详解

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

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

相关文章

Spark 常用算子02

常用Action算子 1、countByKey算子 功能:统计key出现的次数(一般适用于KV型的RDD) 用法: result rdd1.countByKey() print(result)代码示例: # coding:utf8from pyspark import SparkConf, SparkContextif __name…

破解五角大楼3.0漏洞赏金计划专注于设施控制系统

国防部正在计划其“黑掉五角大楼”计划的第三次迭代,重点是找出维持标志性建筑和地面运行的操作技术中的漏洞。 国防部于 2016 年启动了黑客入侵五角大楼计划,供应商 HackerOne 协调了该部门公共网站上的漏洞赏金计划。 超过 1,400 名黑客参加了第一轮…

绝对空前!!!互联网史上的最大ddos攻击惊艳登场

美国遭遇史上最大黑客攻击,知名网站全部瘫痪。全世界一半的网络被黑客攻陷,大网站无一幸免。就在(10月22日),美国早上我们见证了互联网建立以来的最大ddos攻击,twitter、netflix、paypal、reddit、pinteres…

【MySQL】锁

文章目录基础MyISAM表锁并发插入锁调度策略InnoDB事务并发事务行锁行锁争用情况行锁实现方式恢复和复制对InnoDB锁机制的影响死锁MVCC底层实现和原理悲观锁和乐观锁基础 锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。在数据库中&…

一文打通java线程

基本概念:程序、进程、线程 程序(program) 是为完成特定任务、用某种语言编写的一组指令的集合。即指一 段静态的代码,静态对象。 进程(process) 是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有它自身的产…

Linux常用命令——sort命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) sort 将文件进行排序并输出 补充说明 sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。sort命令既可以从特定的文件,也可以从stdin中获取输入。 语法…

文本情感分类TextCNN原理+IMDB数据集实战

1.任务背景 情感分类: 发展历程: 2.数据集 本次使用IMDB数据集进行训练。 3.模型结构 3.1 CNN基础 卷积: 单通道卷积:每组卷积核只包含一个。 单通道输入 单输出:设置一组卷积核。 单通道输入 多输出:…

国企避坑:to B服务性质的业务线不要来!又卷又累,互联网和它比简直是小巫见大巫!...

国企好归好,但不是所有的国企都能闭眼入,一位网友友情提示大家:不管是国企还是央企,to b服务性质的业务线不要来,不要来,不要来!又卷又累,苦哈哈,互联网和这个比&#xf…

在CSS世界的权力——权重

在CSS的世界中也存在着权力即CSS权重 1. 概念 CSS权重指的是样式的优先级,有两条或多条样式作用于一个元素,权重高的那条样式对元素起作用,权重相同的,后写的样式会覆盖前面写的样式 2. 以前的BUG 在实际开发中,我…

代码随想录--双指针章节总结

代码随想录–双指针章节总结 1.LeetCode27 移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 …

C++程序设计——动态内存管理

一、C/C内存分布 1.栈(堆栈) 存储非静态局部变量、函数参数、返回值等等,栈是向下增长。 2.内存映射段 是高效的I/O映射方式,用于转载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程间通信。 3.堆 用…

WPS的简单JS宏应用

有一阵子没写博客了,各种琐事忙碌;前段时间接触了下WPS的宏功能,抽点时间写个学习笔记吧。 案例背景简单说一下,主任让我统计OA后台在建工程项目的概况,后台数据导出一张表,再问隔壁经营部的同事要了一张中…

java类的初始化2023018

类的初始化: 第一次使用某个类,例如Person类,系统通常会在第一次使用Person类时加载这个类并初始化这个类。在类的准备阶段,系统将会为该类的类变量分配内存空间,并指定默认初始值。当Person类初始化完成后&#xff0c…

机器学习笔记之深度玻尔兹曼机(二)深度玻尔兹曼机的预训练过程

机器学习笔记之深度玻尔兹曼机——深度玻尔兹曼机的预训练过程引言深度信念网络预训练过程的问题深度玻尔兹曼机的预训练过程(2023/1/24)引言 上一节介绍了玻尔兹曼机系列的相关模型,本节将介绍深度玻尔兹曼机的预训练过程。 深度信念网络预训练过程的问题 在玻尔…

Escher 愛雪磁磚設計法則 - 高雄燕巢深水國小科展指導

“Talk is cheap. Show me the code.” ― Linus Torvalds 老子第41章 上德若谷 大白若辱 大方無隅 大器晚成 大音希聲 大象無形 道隱無名 拳打千遍, 身法自然 “There’s no shortage of remarkable ideas, what’s missing is the will to execute them.” – Seth Godin …

GreenPlum AOCO列存如何将数据刷写磁盘

GreenPlum AOCO列存如何将数据刷写磁盘AOCO列存表每个字段一个文件,前面我们介绍了列存表如何加载数据页,本文我们重点介绍AOCO表如何进行刷写。AOCO表进行insert、update、delete会产生脏数据,和heap表的异步脏页刷写不同,AOCO表…

写一个锅炉温控系统用python编写

简单来说就是锅炉水热了之后循环泵自动开启,然后将热水输送走,送到暖气,热水抽走,凉水进入锅炉,温度降低,循环泵关闭,等待下一次水烧热。因为需要取暖的房子距离烧锅炉的地方比较远,所以需要循环泵,如果距离近的话水烧热后利用热水上流冷水回流的原理会自动完成循环。…

前言技术之mybatis-plus

目录 1.什么是mybatis-plus 2.初体验 3.日志 4.主键生成策略 5.更新 6.自动填充 1.什么是mybatis-plus 升级版的mybatis,目的是让mybatis更易于使用, 用官方的话说“为简化而生” 官网: MyBatis-Plus 2.初体验 1.准备数据库脚本 数据…

BI 解决方案:BimlStudio 22.3.0 Crack

全功能开发环境:::: 导入现有解决方案 通过添加 BimlScript 自动化进行更改并重新生成包;使您的解决方案更好、更快。 可视化整个 BI 解决方案 通过我们的可视化设计器在一个位置进行更改,观察您的整个解决方案自行更新…

【ArcGIS微课1000例】0061:ArcGIS打开xyz格式点云数据的方法

本文讲述ArcMap和ArcScene中如何打开xyz格式的点云数据并做可视化的方法。 文章目录 一、xyz格式点云简介二、ArcMap打开xyz点云三、ArcScene打开xyz点云四、注意事项一、xyz格式点云简介 本实验使用的数据是配套数据包中的0061.rar,斯坦福大学的点云数据,格式为X,Y,Z,如下…