python辗转相除_python(四):辗转相除

摘要:

学习leetcode_365: Water and Jug Problem的解法:辗转相除相关内容(最大公约数、裴蜀定理、欧几里得算法和扩展欧几里得算法)。

正文:

1、问题描述

You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. You need to determine whether it is possible to measure exactly z litres using these two jugs.

If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end.

Operations allowed:Fill any of the jugs completely with water.

Empty any of the jugs.

Pour water from one jug into another till the other jug is completely full or the first jug itself is empty.

Example 1:

Input: x = 3, y = 5, z = 4

Output: True

(**分析**):

首先,将三个操作进行“量化”,一次倒满已知体积的壶的操作,相当于有一个(+1)*Volume,而一次将满壶水倒掉的操作,则相当于(-1)*Volume。这意味着结果可以表示为两个已知体积壶的整数线性组合:

所以,任意给定(x, y, z)且z

2、整数解存在的判据:裴蜀定理

前述方程是否有整数解的解法有一个已经存在的定理(裴蜀定理),其结论是该方程有整数解(m, n)的充要条件是z为x与y的最大公约数gcd(x, y)的倍数。也就是说,如果这个方程有整数解,那么z一定是

,反过来看,也只有当z%gcd(x,y)=0时,整数解才存在。于是,这个问题转化为求x和y的最大公约数,有辗转相除法(欧几里得算法):

(2.1)核心思想,是如下等式,对于正整数p和q(若p>q),p除以q的余数为r,则有:

由于显然有p>q>r,这个等式将两个较大数的公约数求解转化为两个较小数的公约数;

(2.2)这个最大公约数等式可以往下继续写:

其中从第一个等式开始,后式括号里的第一项为前式括号里的较小数、第二项为前式括号里较大数和较小数相除的余数。最后总能到一个余数为0的情况,此时的第一项即为p和q的最大公约数;

(2.3)这个算法可以用递归的思想很好地表达出来,python代码如下:

test of gcd:这两组数的最大公约数都是6

那么,leetcode_365就迎刃而解了,代码如下:

test of canMeasureWater:题目的example随机输入3个正整数进行测试

3、整数解的求解:扩展欧几里得算法

判断了能否测量,进一步就会思考如何进行测量呢?这个实际上就是在求前述方程的整数解。这里的解法类似于辗转相除法,也即扩展欧几里得算法。需要注意的是,由于px+qy=c的整数解从几何意义上来说是检查一条直线过整数格点的情况,所以当然可以不止一个解,而扩展欧几里得算法得到的只是其中一个。

首先从一个例子来感受一下该算法:

(a)方程系数(20, 12)变为(12, 8):

假设

,则变为:

(b)继续将(12, 8)变为(8, 4):

假设

,则变为:

(c)继续将(8, 4)变为(2, 0):

假设

,则变为:

(d)最后一个解(x3, y3)=(1, 0),那么从括号里的递推公式,依次有:(x2, y2)=(0, 1),(x1, y1)=(1, -1),(x0, y0)=(-1, 2),最后一项即为原方程的一个解。

形如

的方程总是可以用(a)-(d)来求解。整个过程和辗转相除类似(方程系数就是在做辗转相除),而且如果方程有解(c%gcd(p,q)=0),那最后的解肯定是(c/gcd(p,q), 0),因为系数辗转相除总是会到(gcd(p,q), 0)。其中变量转换的递推公式比较关键,但也很好理解,推广一下就是(//和python的整数除法定义一致):

python实现代码如下:这里先求解px+qy=gcd(p,q),再转换为px+qy=c的解;这样操作只是为了逻辑更清晰,实际上可以整合在一起(递归结束时返回值从(1, 0)变为(c/gcd(p,q), 0))px+qy=gcd(p,q)的解,求解过程不依赖于方程左边的c;以(p,q)为递归过程,再反向递归求解(x,y)

test of integer_solution:实际上还有x=-2, y=2的解,多解的原因应该是前述(c)步骤中,最后一次变量转换实际上可以不遵从递推公式

从这个结果可知,如果想用3升和5升的水壶生成4升容积,解(8,-4)意味着总共会倒入8次3升水壶、倒掉4次5升水壶,而解(-2, 2)意味着总共会倒掉2次3升水壶、倒满2次5升水壶。当然,解只是总体概括,至于具体步骤还需要进一步地分解了,不过问题就已经变得很简单了。

4、本篇内容代码的github链接gcd_euclidean_algorithm.py​github.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值