欧几里得算法扩展之裴蜀公式-求解线性方程的一个解

1.对任意整数a,b和他们的最大公约数d,关于未知数x和y的线性丢番图方程(称为裴蜀等式)
ax+by=m有整数解的时候当且仅当m是d的倍数
裴蜀公式有解的时候必然有无穷多个整数解,每组解x,y都称为裴蜀数,可以用欧几里得算法求得

特别地ax + by = 1 有整数解当且仅当整数a和b互为素数

在求解线性方程组ax + by = k的时候求解最大公约数

由其中的过程递推出如下的规律:

往下求解最大公约数的过程中,x1和y1分别是下一次的x和y

例如线性方程:2x + 7y = 1求解整数解

可以知道a = 2, b = 7依次求出最大公约数(使用递归来解决)

(2,7)

(7,2)

(2,1)     

(1,0)     

最后结束递归得到x1 = 1 y1 = 0但是此时的a和b不是原来的a和b了,需要往上来递推得到新的x1和y1

那么可以得到

(2,7)    x1 = -3 y1 = 1

(7,2)    x1 = 1 y1 = -3

(2,1)    x1 = 0 y1 = 1

(1,0)    x1 = 1 y1 = 0

层层往上推最后得到原来的x和y,那么这样就可以使用递归更新解决x1和y1来最终得到线性方程组的一组整数解

代码如下:
public class Main{
    //全局变量易于修改
    static long x;
    static long y;
    public static void main(String[] args) {
        try {
            linearEquation(2, 3, 1);
            System.out.println(x+" "+y);
        } catch (Exception e) {
            System.out.println("无解");
            e.printStackTrace();
        }
    }
    
    //可以查看截图可以知道可以使用递归的方式来解决线性方程组的问题
    //自己可以在纸上推一下就知道了
    //记住公式:y = x1 - a/b*y1
    private static long ext_gcd(long a,long b){
        if(b==0){
            x = 1;
            y = 0;
            return a;
        }
        //当碰到递归出口的时候依次返回上一层然后更新x1和y1直到更新到一开始调用这个函数的a,b
        //递归我们要心安理得的调用
        long res = ext_gcd(b,a%b);
        //备份一下x因为后面有交换这个值这样结果才会正确
        long x1 = x;
        x = y;
        y = x1 - (a/b)*y;        
        return res;
    }
    
    //因为上面求解的是ax+by=d的线性方程组d是a和b的最大公约数,而我们要求解的是ax+by=m的线性方程组
    //当m是d的倍数的时候那么这个方程组有整数解
    private static long linearEquation(long a,long b,long m) throws Exception{
        long d = ext_gcd(a,b);
        if(m%d!=0){
            throw new Exception("无解");
        }else{
            long n = m / d;
            x *= n;
            y *= n;
        }
        return d;
    }
}
 

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/82709276