二元一次不定方程(形如 a * x + b * y = c的方程,又叫丢番图方程,下简称不定方程),是初等数论经典的研究对象。二元一次不定方程应用广泛,如经典的找换问题和装箱问题(下面我将通过一系列的文章来解释我如何通过求解不定方程来快速解决装箱问题)。所谓的找换问题,举个例子就是有1分硬币若干个,3分硬币若干个,如果现在要买一个一块钱的东西,我要给多少个这两种硬币。当然丢番图方程的用处不仅限于此,就连大名鼎鼎的公务员考试都有类似这样的问题。
求解二元一次不定方程有多种解法。而网络上流行最多的是暴力破解法- -!。事实上,关于二元一次不定方程的整数解在数学上已经有相当完满的答案。
定理1:现有不定方程a * x + b * y = c,a,b,c均为整数,若d=GCD(a,b)(GCD表示取a,b的最大公约数),d|c(d整除c),那么二元一次不定方程必定有解,且有无数解。
例子:3x + 4y = 5(随便定的)有解,因为1= GCD(3,4) ,1 | 5。易知当x=-5,y=5时,即得整数解。
这定理相关的数学证明就参看数论相关的资料,这里只阐述结论。(下同)
定理2:若不定方程a * x + b * y = c有整数解,则通解的形式必定为X=x0 + b/d * n, Y = y0 + a/d * n。其中x0,y0为不定方程的一个整数解。
引用上面的例子,易知其通解为X=-5+4n,Y = 5+3n。n为整数
定理1给出不定方程解的一个判定方法,而定理2则给出了不定方程通解的形式。
虽然上述结论,已经似乎很完美,但事实上还有一个重要的地方没有解决,就是如何快速求解不定方程。暴力破解当然不可取,因为这会极其浪费计算机资源。而且当a和b足够大时,几乎是求解不了。事实上解不定方程,有一个强劲的解法,叫扩展欧几里德算法,也叫辗转相除法,使用欧几里德算法,时间复杂度为O(logN)的。而即使优化过的暴力法也至少需要O(n)。
继续使用上面的例子,我们拿4除以3,得1,余1,这样,我们可以得到如下等式1=4 - 3 * 1。1刚好能整除5。(事实上1能整除任何整数)
这样等式两边同时乘以5,即得 5 = 4 * 5 - 3 * 5。由此马上可以知方程的一个解为(-5,5)。
这只是巧合吗?再试试别的数,考察不定方程16 X + 21Y = 5。能不能也用辗转相除法做呢?答案是肯定的。
21除15,得1,余7,写成等式形式5 = 21 - 16 * 1(1)。7不能整除5。到这就没辙了吗?不!所谓的辗转相除法,就是要把参与运数的两个数相除得到余数要么变成1,要么就根本不存在余数。继续取除数16,和余数5作为运算对象。
15除7,得1,余8,等式形式1=16 - 5 * 3 (2)。余数为1,结束。
得到余数为1的等式有什么用?我们把(1)式代入(2)式中的5,得到1=16 - (21 - 16 * 1) * 3 = 16 * 4 - 21 * 3。
算到这,又可以使用上面的方法,两边乘以5,得特解(20,15)(读者可以自行代入验证)。
上面的例子都是a跟b互质的情况(最大公约数为1),如果a跟b不互质呢?不互质的情况,欧几里德算法也一样适用,因为欧几里德算法本身的用途就是用来求解最大公约数。得到最大公约数d,再通过反复回代的办法,将其表示成d = a * x' + b * y'形式,就可以得到 c = a * x' * k + b * y' * k ,其中k = c / d。进一步得到特解x0 = x' * k, y0 = y' * k。事实上,现在数论上研究不定方程解的文章,也只研究a跟b互质的情况,因为不管a,b,c取何值,只要等式上两边同时除以公约数就可以得到a跟b互质的不定方程。求得此特殊的不定方程的解,就能通过乘以公约数d,得到原方程的解。
这才是求解二元一次不定方程的真正打开方式。
事实上,对于一些特殊的不定方程,还有更快速的解法。前提是a跟b的最大公约数已知
推论1:若a * x + b * y = c有整数解,且a=d=GCD(a,b),b = k * d, c = k' * d,则马上有x0= (k + 1) * k', y0 = - k'。
证明:将特解入方程等号左边即有 a * (k + 1) * k' - b * k = a * k * k' - b * k + a * k',由于 a = d ,所a * k * k' = b * k' , a * k' = c,所以 原式等于 b * k' - b * k' + c = c,等式两边成立。
此推论的用处,在于不需要透过欧几里德算法回代来求方程,只需要简单的4步计算就可以求解。
例子6X + 12 Y = 12 , 6 | 12, 12 / 6 = 2 。根椐推论马上可以得到特解x0= (2 + 1 ) * 2 = 6, y0 = -2。
这个推论适用于任何a,b之间存在整除关系的不定方程。
下面的这个推论进一步扩大推论1的适用范围。
推论2:若a * x + b * y = c有整数解,d=GCD(a,b),a = t1 * d, b = t2 * d,若 t1 = - 1 = t2 - 1(mod t2 ) (同余式一般取最小正剩余),k = (t1 + 1 ) / t2 , k ' = c / d,则马上有x0= - c / d, y0 = k * c / d。
证明:将x0= -c , y0 =kc 代入原方程左式得 - a * c / d + b * k * c / d ,由a = t1 * d ,b = t2 * d ,k = (t1 + 1) / t2 ,得
-a * c / d + b * k * c / d = - t1 * c + t2 * ((t1 + 1) / t2) * c = - t1 * d * c + t1 * d * c + c = c
命题得证。
例子:7x + 4y = 5,易知d = 1 , 7 = -1(mod 4),k = (7 + 1) / 4 =2 ,代入特解公式得x0 = - 5 / 1 = -5,y0= 2 * 5 / 1 =10。
代入原方程 7 * (-5) + 4 * 10 = 5。刚好是方程的解。
推论2比推论1的约束条件更弱,只要满足t1 = t2-1(mod t2)就够了,这样,型似 (t-1)x + ty = c的不定方程可以马上得其通解。
事实上,由推论2推导出的还有一个更强力的推论3,可以继续扩大其适用范围。
推论3:若a * x + b * y = c有整数解,d=GCD(a,b),a = t1 * d, b = t2 * d,, q = c / n,k = (t1 + n ) / t2 , k ' = c / d,若 t1 = -n(mod t2 ) ,n整除k',q = k' / n,则马上有x0= - c / q * d, y0 = k * c / q * d。
推论2与推论1的证明类似,只是在分母部分多了个q,读者可自行证明,这里不再赘述。
举例:8x + 5y = 4, d = 1, t1 = 7 , t2 = 5 , 8 = -2(mod 5), 2 | 4 ,k = (8 + 2) / 5 = 2, q = 4 / 2 = 2,则马上有特解x0 = - 4 / 2 * 1 = -2 ,y0 = 2 * 4 / 2 * 1 = 4,代入原方程得 8 * ( -2 ) + 5 * 4 = 4 。
至此,所有形如 t1 = t2 - n (mod t1 ),n | k ,都可以使用此快速解法。在上述运算过程中,只做了4次四则运算,比使用辗转回代法的运算速度还要快。
最后,讨论最后一种特殊的不定方程a * x + b * y = 0
推论4:方程a * x + b * y = 0必定有解,且通解为x = - t2 + (b / d) * n , y = t1 - (a / d) * n。其中t1 = a / d ,t2 = b / d。
将特解通解回代即得证明,这里不再赘述。
通过以上4个推论,至少可以把很大一部分的二元一次方程在常数次(4次左右)四则运算内解决掉,比穷举法高效得多。很多人在解二元一次不定方程使用穷举法,实际上是由于数论知识的薄弱。
(程序化版本稍后贴出)
笔者语:二元一次不定方程的特解和通解都有很成熟的结论,但多元一次就不太好办,多元一次的特解求解容易,但通解却可以透过引入多个参变量来进行构造。下文将透过系列文章来讨论