【算法】欧几里得与拓展欧几里得算法

ops/2024/11/27 10:26:00/

目录

一、欧几里得算法

二、拓展欧几里得算法

2.1 裴蜀定理

2.2 拓展欧几里得算法

2.3 例题

三、线性同余方程

3.1 概念

3.2 例题


一、欧几里得算法

欧几里得算法又称辗转相除法,可用于求解两个数的最大公约数

其思路:

  • gcd(a, b) = gcd(b, a%b),其中gcd(a, b)代表a和b的最大公约数
  • 当b=0时,a为最大公约数

例如要求36和24的最大公约数即gcd(36, 24),可转而求gcd(24, 36%24)即gcd(24, 12),再转为求gcd(12, 0),此时最大公约数即为12

其代码实现:

int gcd(int a, int b)
{if(b == 0)return a;return gcd(b, a % b);
}


二、拓展欧几里得算法

2.1 裴蜀定理

  • 若a,b是整数,且d = gcd(a, b),则对于任意的整数x和y,总有ax+by是d的倍数
  • 对于给定的整数x和y,方程ax+by=c有整数解(x, y)的充分必要条件是c是gcd(a, b)的倍数

2.2 拓展欧几里得算法

由裴蜀定理,我们知道对于给定的整数a和b,方程ax + by = gcd(a, b)总有整数解(x, y)

那么,如何求出这个整数解(x, y)?

  1. 由欧几里得算法可得gcd(a, b) = gcd(b, a%b)
  2. 由裴蜀定理,bx' + (a%b)y' = gcd(b, a%b)
  3. 由1和2,得bx' + (a%b)y' = gcd(a, b) 即 ax + by = bx' + (a%b)y'
  4. 由a%b = a - b*(a/b)【注意这里的a/b是向下取整】,得ax + by = bx' + [a - b*(a/b)]y'
  5. 上式整理得a(x-y') - b[x' - y - (a/b)y'] = 0,即x-y'=0、x' - y - (a/b)y'=0
  6. 得x = y',y = x'-(a/b)y'

得到求解后,我们就可以通过递归不断传入x和y来计算整数解(x, y)了。拓展欧几里得的递归终点和欧几里得的终点类似,当b为0时即ax+by = a时返回{x=1,y=0}的解,并通过上一次的结果向下更新

拓展欧几里得算法的代码实现:

int exgcd(int a, int b, int &x, int &y) //扩展欧几里得算法
{if(b == 0) //b为0时结束递归{x = 1; //ax+by=a->x=1,y=0y = 0;return a;}int gcd = exgcd(b, a%b, y, x); //递归求x'和y'y -= (a/b) * x; //此时递归后x=y',y=x',将y=x'-(a/b)y'转为y=y-(a/b)x得y-=(a/b)x return gcd;
}

2.3 例题

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define debug(x) cout << #x << " = " << x << '\n'
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;int n, a, b, x, y;int exgcd(int a, int b, int &x, int &y) //扩展欧几里得算法
{if(b == 0) //b为0时结束递归{x = 1; //ax+by=a->x=1,y=0y = 0;return a;}int gcd = exgcd(b, a%b, y, x); //递归求x'和y'y -= (a/b) * x; //此时递归后x=y',y=x',将y=x'-(a/b)y'转为y=y-(a/b)x得y-=(a/b)x return gcd;
}void solve()
{cin >> n;for(int i = 0;i < n; i++){cin >> a >> b;exgcd(a, b, x, y);cout << x << " " << y << endl;}
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;// cin >> t;while (t--)solve();return 0;
}


三、线性同余方程

3.1 概念

线性同余方程ax ≡ b(mod m),要求我们求出一个整数x,使得a和x的乘积模上m等于b

对于这个方程,可以用拓展欧几里得算法求解:

  1. ax ≡ b(mod m)可转化为对于整数x,存在整数y使得ax = my + b
  2. 令y' = -y,则上式转化为ax + my' = b
  3. 用拓展欧几里得算法求ax' + my' = gcd(a, m)
  4. 只要b是gcd(a, m)的倍数则说明方程成立,整数x存在,x = x' * (b / gcd(a, m))

3.2 例题

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define debug(x) cout << #x << " = " << x << '\n'
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;int n, a, b, m, x, y;int exgcd(int a, int b, int &x, int &y) //扩展欧几里得算法
{if(b == 0) //b为0时结束递归{x = 1; //ax+by=a->x=1,y=0y = 0;return a;}int gcd = exgcd(b, a%b, y, x); //递归求x'和y'y -= (a/b) * x; //此时递归后x=y',y=x',将y=x'-(a/b)y'转为y=y-(a/b)x得y-=(a/b)x return gcd;
}void solve()
{cin >> n;for(int i = 0;i < n; i++){cin >> a >> b >> m;int gcd = exgcd(a, m, x, y);if(b % gcd == 0) //b是gcd倍数:成立cout << x * (b / gcd) % m << endl; //为什么要%m?因为可以保证x在int范围内且同余belse //b不是gcd倍数:无解cout << "impossible" << endl;}
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;// cin >> t;while (t--)solve();return 0;
}

完.


http://www.ppmy.cn/ops/137052.html

相关文章

241126学习日志——[CSDIY] [ByteDance] 后端训练营 [19]

CSDIY&#xff1a;这是一个非科班学生的努力之路&#xff0c;从今天开始这个系列会长期更新&#xff0c;&#xff08;最好做到日更&#xff09;&#xff0c;我会慢慢把自己目前对CS的努力逐一上传&#xff0c;帮助那些和我一样有着梦想的玩家取得胜利&#xff01;&#xff01;&…

Deepnote、JupyterLab、Google Colab、Amazon SageMaker、VS Code对比

功能比较 平台语言支持扩展性数据连接可视化能力DeepnotePython、R、SQL中等&#xff0c;依赖云端支持主要云平台&#xff08;BigQuery、Snowflake等&#xff09;内置仪表盘与交互图表JupyterLab多种语言&#xff0c;插件支持广泛极高&#xff0c;完全可自定义使用库&#xff…

【C++】list模拟实现(完结)

1.普通迭代器&#xff08;补充&#xff09; 1.1 后置和后置-- 我们迭代器里面实现了前置和前置--&#xff0c;还需要实现后置和后置--。 在list.h文件的list_iterator类里面实现。 //后置/-- Self& operator(int) {Self tem(*this);//保存原来的值_node _node->_nex…

111.有效数字

class Solution {public boolean isValid(String word) {if(word.length()<3){return false;}int countV0,countC0;//分别统计原音和辅音for(int i0;i<word.length();i){if(Character.isLetterOrDigit(word.charAt(i))){if(word.charAt(i)a||word.charAt(i)e||word.charA…

Xcode15(iOS17.4)打包的项目在 iOS12 系统上启动崩溃

0x00 启动崩溃 崩溃日志&#xff0c;只有 2 行&#xff0c;看不出啥来。 0x01 默认配置 由于我开发时&#xff0c;使用的 Xcode 14.1&#xff0c;打包在另外一台电脑 Xcode 15.3 Xcode 14.1 Build Settings -> Asset Catalog Compliter - Options Xcode 15.3 Build S…

Flutter实现tts语音播报

目录 引言 添加flutter_tts依赖 设置语言和发音人 macOS Android iOS 说话、停止、获取语言、设置语言、设置语音速率、获取声音、设置声音、设置音量、设置音高、是否语言可用、设置共享实例 监听平台 封装代码 使用案例 引言 随着移动应用的不断发展&#xff0c;…

godot游戏引擎_瓦片集和瓦片地图介绍

在 Godot 中&#xff0c;TileSet 和 TileMap 是用于处理瓦片地图的两个关键概念&#xff0c;它们的作用和用途有明显的区别。以下是两者的详细对比&#xff1a; 1. TileSet&#xff08;瓦片集&#xff09; TileSet 是资源&#xff0c;定义瓦片的内容和属性。 特点&#xff1a…

【Electron学习笔记(二)】基于Electron开发应用程序

基于Electron开发本地应用程序 基于Electron开发本地应用程序前言正文1、创建 pages 目录2、创建 index.html 文件3 、创建 html.css 文件4 、main.js里引入页面5 、运行 start 命令6 、启用开发者模式7 、解决内容安全策略8、完善窗口行为9、配置自动重启&#xff0c;保存后自…