当前位置: 首页 > news >正文

欧几里得扩展算法扩展欧几里得

欧几里得算法

欧几里得算法又称为辗转相除法  用来计算gcd(a , b)

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

时间复杂度:O(log(b))

证明如下:

gcd(a,b)=gcd(b,a mod b)
证明:a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个公约数,则有
d|a, d|b,而r = a - kb,因此d|r
因此d是(b,a mod b)的公约数
假设d 是(b,a mod b)的公约数,则
d | b , d |r ,但是a = kb +r
因此d也是(a,b)的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证
扩展算法
算法描述:对于完全不为0的非负整数a , b。gcd(a , b)表示a , b的最大公约数,必然存在整数x , y,使得gcd(a , b) = a*x+b*y。
证明如下:
设 a>b。
1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
2,a>b>0 时
设 ax1+ by1= gcd(a,b);
bx2+ (a mod b)y2= gcd(b,a mod b);
根据朴素的 欧几里德原理有 gcd(a,b) = gcd(b,a mod b);
则:ax1+ by1= bx2+ (a mod b)y2;
即:ax1+ by1= bx2+ (a - [a / b] * b)y2=ay2+ bx2- [a / b] * by2;
说明: a-[a/b]*b即为mod运算。[a/b]代表取小于a/b的最大整数。
也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2);
根据恒等定理得:x1=y2; y1=x2- [a / b] *y2;
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。
算法实现:
int kuo_zhan(int a , int b , int &x , int &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int q = gcd(b , a%b , y , x);
    y -= a/b*x;
    return q;
}

部分变换:

变换之后实现如下:

int kuoz_zhan_2(int a , int b , int &x , int &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int q = gcd(b , a%b , x , y);
    int tmp = x;
    x = y;
    y = tmp-a/b*y;
    return q;
}

证明如下:

把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。
可以这样思考:
对于a'=b,b'=a%b 而言,我们求得 x, y使得 a'x+b'y=Gcd(a',b')
由于b'=a%b=a-a/b*b (注:这里的/是程序设计语言中的除法)
那么可以得到:
a'x+b'y=Gcd(a',b') ===>
bx+(a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===>
ay +b(x - a / b*y) = Gcd(a, b)
因此对于a和b而言,他们的相对应的p,q分别是 y和(x-a/b*y)
一般解:
上面已经列出找一个 整数解的方法,在找到p * a+q * b = Gcd(a, b)的一组解p0,q0后,p * a+q * b = Gcd(a, b)的其他整数解满足:
p = p0 + b/Gcd(a, b) * t
q = q0 - a/Gcd(a, b) * t(其中t为任意整数)
扩展欧几里得
算法描述:扩展欧几里得可以解决不定方程求解问题,如a*x+b*y=c,其中c=gcd(a , b)时为扩展问题,c不为gcd(a , b)时,需要满足c%gcd(a , b)=0才会有解,否则无解
证明略。
至于pa+qb=c的整数解,只需将p * a+q * b = Gcd(a, b)的每个解乘上 c/Gcd(a, b) 即可,但是所得解并不是该方程的所有解,找其所有解的方法如下:
在找到p * a+q * b = Gcd(a, b)的一组解p0,q0后,可以
得到p * a+q * b = c的一组解p1 = p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),p * a+q * b = c的其他整数解满足:
p = p1 + b/Gcd(a, b) * t
q = q1 - a/Gcd(a, b) * t(其中t为任意 整数)
p 、q就是p * a+q * b = c的所有整数解。

转载于:https://www.cnblogs.com/Flower-Z/p/9340342.html

相关文章:

  • Spring Boot 2.0 整合 ES 5 文章内容搜索实战
  • HyperLedger Fabric ca正式环境部署
  • mysql-ubuntu14.04彻底卸载mysql
  • 检测对象或数组
  • Python--作业2--对员工信息文件,实现增删改查操作
  • BAT面试常的问题和最佳答案
  • MFS分布式文件系统服务搭建
  • redis系列:通过文章点赞排名案例学习sortedset命令
  • 自抗凝透析器研究取得系列进展
  • (转)visual stdio 书签功能介绍
  • 如何高效学习和工作(撸代码)
  • python代码-leetcode1 两数相加
  • WPF 简洁的主界面
  • PowerDesigner使用小总结
  • 用开源技术巧解代账公司开票据难题
  • python3.6+scrapy+mysql 爬虫实战
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • css布局,左右固定中间自适应实现
  • docker-consul
  • express + mock 让前后台并行开发
  • gcc介绍及安装
  • hadoop集群管理系统搭建规划说明
  • HomeBrew常规使用教程
  • JavaScript中的对象个人分享
  • Java读取Properties文件的六种方法
  • Java基本数据类型之Number
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Meteor的表单提交:Form
  • spring cloud gateway 源码解析(4)跨域问题处理
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • SQLServer之创建显式事务
  • 大主子表关联的性能优化方法
  • 解析带emoji和链接的聊天系统消息
  • 事件委托的小应用
  • 收藏好这篇,别再只说“数据劫持”了
  • 思考 CSS 架构
  • 微信开源mars源码分析1—上层samples分析
  • 无服务器化是企业 IT 架构的未来吗?
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • FaaS 的简单实践
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​io --- 处理流的核心工具​
  • ​linux启动进程的方式
  • ​queue --- 一个同步的队列类​
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (1)Android开发优化---------UI优化
  • (HAL库版)freeRTOS移植STMF103
  • (poj1.2.1)1970(筛选法模拟)
  • (超详细)语音信号处理之特征提取
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)