欧几里得与扩展欧几里得算法(含推导过程及代码)
创始人
2024-05-16 08:23:12
0

文章目录

  • 前言
  • 一、欧几里得算法
  • 二、扩展欧几里得算法
    • 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为0arr[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,yint[] 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’ = ad\frac{a}{d}da​,b‘ = bd\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’ = ad\frac{a}{d}da​,b‘ = bd\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 = 17ok,此时x0 = -7,y0 = 17,我们来自己通过公式去尝试构造一组解,设置k = 2,x = -7 + 2 * 5 = 3y = 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]. 扩展欧几里得算法详解

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...