裴蜀定理详细介绍

一、裴蜀定理的定义

裴蜀定理(也叫贝祖定理)(Bézout’s identity)简单来说就是:对于两个整数 ( a ) 和 ( b ),它们的最大公约数 ( d ) 可以表示成 ( a ) 和 ( b ) 的线性组合。也就是说,一定存在整数 ( x ) 和 ( y ),使得

a x + b y = d ax + by = d ax+by=d

示例:

假设 ( a = 15 ) 和 ( b = 10 )。它们的最大公约数是 5,也就是 ( gcd(15, 10) = 5 ) 。根据裴蜀定理,应该存在一些整数 ( x ) 和 ( y ),使得:

15 x + 10 y = 5 15x + 10y = 5 15x+10y=5

事实上,( x = 1 ) 和 ( y = -1 ) 就是满足这个等式的一组解,因为:

15 ⋅ 1 + 10 ⋅ ( − 1 ) = 15 − 10 = 5 15 \cdot 1 + 10 \cdot (-1) = 15 - 10 = 5 151+10(1)=1510=5

通过这个例子我想表示:任何两个整数的最大公约数都可以写成这两个整数的某种倍数之和

另外如果已知整数(a)和(b),那么gcd(a,b)以及对应的系数 x 和 y 是很好求解的。

注意:GCD 是 Greatest Common Divisor 的缩写,意思是最大公约数。gcd(a,b)就是a和b的最大公约数。

二、欧几里得算法

这不讲裴蜀定理呢,怎么冒出个欧几里得算法???
实际上裴蜀定理和欧几里得算法之间的关系还是很紧密的;可以通过欧几里得算法求解裴蜀定理中的a和b对应的系数xy,以及它们的最大公约数gcd(a,b);接下来我会通过Java代码来演示如何求解gcd(a,b)、x、y。

1. 求解gcd(a,b)

gcd(a,b)的定义

给定两个整数a和b,gcd(a,b)是a和b的最大公约数。也就是说gcd(a,b)是既满足可以整除a又满足可以整除b的最大的整数。此外,gcd(a,b)一定是一个非负数。

示例:

  • 给定 ( a = 12 ) 和 ( b = 18 )
  • ( 12 ) 的正约数有:( 1, 2, 3, 4, 6, 12 )
  • ( 18 ) 的正约数有:( 1, 2, 3, 6, 9, 18 )
  • 这两个数的公共约数是 ( 1, 2, 3, 6 ),其中最大的公共约数是 ( 6 )

所以,gcd(12, 18) = 6


代码求解gcd(a,b)

import java.util.Scanner;
import java.lang.Math;

public class Test {
    private static int getGcd(int a,int b){
    //如果b是0,那么a的绝对值就是最大公约数
        if(b==0)return Math.abs(a);
        
        //b!=0就一直递归
        else return getGcd(b,a%b);
    }
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        int gcd=getGcd(in.nextInt(),in.nextInt());
        
        System.out.println(gcd);
    }
}

2、求解x和y

可以根据欧几里得算法,也就是上面的递归,持续跟踪系数x和y。
首先我们创建一个类来存储每次递归a和b对应的最大公约数以及两个系数:

//裴蜀定理:ax + by = gcd(a,b);
static class ResultGCD{
        int gcd;
        int x;
        int y;
        public ResultGCD(int gcd, int x, int y) {
            this.gcd = gcd;
            this.x = x;
            this.y = y;
        }
    }

然后对getGcd函数进行修改:

private static ResultGCD getGcd(int a, int b){

        //a*1 + b*0 = gcd(a,b) = a;
        if(b==0)return new ResultGCD(a,1,0);

        else{
            //对应的a=a  b=a%b!!!
            ResultGCD result=getGcd(b,a%b);
            
            //下面的6行代码如果初次接触,可能就看不懂了
            int x1=result.x;
            int y1=result.y;
            int gcd=result.gcd;
            int x=y1;
            int y=x1-(a/b)*y1;
            return new ResultGCD(gcd,x,y);
        }
    }

上面的6行代码是根据简单的数学公式推导过来的,具体推导步骤如下:


推导步骤

假设我们已经得到了较小规模问题的解,即对于b和a%b,有:

b ⋅ x 1 + ( a % b ) ⋅ y 1 = gcd ⁡ ( b , a % b ) b \cdot x_1 + (a \% b) \cdot y_1 = \gcd(b, a \% b) bx1+(a%b)y1=gcd(b,a%b)

根据模运算的定义, a % b = a − ( a b ) ⋅ b a \% b = a - \left( \frac{a}{b} \right) \cdot b a%b=a(ba)b 例如: ( 11 % 5 = 11 − ( 11 5 ) ⋅ 5 ) (11 \% 5 = 11 - \left( \frac{11}{5} \right) \cdot 5) (11%5=11(511)5)
所以上面的等式可以写成:

b x 1 + ( a − ( a b ) b ) y 1 = gcd ( a , b ) b x_1 + \left(a - \left(\frac{a}{b}\right) b \right) y_1 = \text{gcd}(a, b) bx1+(a(ba)b)y1=gcd(a,b)

展开后得到:

a y 1 + b ( x 1 − ( a b ) y 1 ) = gcd ( a , b ) a y_1 + b \left(x_1 - \left(\frac{a}{b}\right) y_1 \right) = \text{gcd}(a, b) ay1+b(x1(ba)y1)=gcd(a,b)

因此,解可以递推为:

x = y 1 x = y_1 x=y1

y = x 1 − ( a b ) y 1 y = x_1 - \left(\frac{a}{b}\right) y_1 y=x1(ba)y1

代码中的推导

在代码中,这一步对应于以下几行:

ResultGCD result=getGcd(b,a%b);
int x1=result.x;
int y1=result.y;
int gcd=result.gcd;

int x = y1;
int y = x1 - (a / b) * y1;
return new ResultGCD(gcd,x,y);

总的来说,推导方式还是很简单,把%运算替换一下就成了。但如果不太理解可以把上面求解x和y的公式记下来也没问题。

求解gcd(a,b)、x、y的完整代码


import java.util.Scanner;
import java.lang.Math;

public class Test {

    static class ResultGCD{
        int gcd;
        int x;
        int y;
        public ResultGCD(int gcd, int x, int y) {
            this.gcd = gcd;
            this.x = x;
            this.y = y;
        }
    }


    private static ResultGCD getGcd(int a, int b){

        //a*1 + b*0 = gcd(a,b) = Math.abs(a);
        if(b==0)return new ResultGCD(Math.abs(a),1,0);

        else{
            //对应的a=a  b=a%b!!!
            ResultGCD result=getGcd(b,a%b);

            //下面的6行代码如果初次接触,可能就看不懂了
            int x1=result.x;
            int y1=result.y;
            int gcd=result.gcd;
            int x=y1;
            int y=x1-(a/b)*y1;
            return new ResultGCD(gcd,x,y);
        }
    }
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
         ResultGCD ans=getGcd(in.nextInt(),in.nextInt());

        System.out.println("gcd="+ans.gcd);
        System.out.println("x="+ans.x);
        System.out.println("y="+ans.y);
    }
}

三、裴蜀定理的推论

裴蜀定理的结论
对于任意整数 (a) 和 (b),存在整数 (x) 和 (y),使得: a x + b y = gcd ⁡ ( a , b ) ax + by = \gcd(a, b) ax+by=gcd(a,b)

1. 可整除性条件

对于任意整数 (a) 和 (b),如果 (d = gcd(a, b)),那么对于任意整数 (k),存在整数 (x) 和 (y) 使得:
a x + b y = k 当且仅当 k 是 d 的倍数 ax + by = k \quad \text{当且仅当} \quad k \text{是} d \text{的倍数} ax+by=k当且仅当kd的倍数

2. 互质与最大不能表示数

d = gcd ⁡ ( a , b ) d= \gcd(a, b) d=gcd(a,b) 并且 d = 1 d=1 d=1,那么a和b一定互质。且存在一个正整数 M A X MAX MAX , M A X MAX MAX是a和b的线性组合最大不能表示的整数。换句话说,任何大于 M A X MAX MAX的整数都可以通过ab的线性组合表示。 其中: M A X = a b − a − b MAX=ab-a-b MAX=abab

3. 两数之和构成的整数集合

若 (a) 和 (b) 互质(即 (gcd(a, b) = 1)),则所有形如 (ax + by) 的整数(其中 (x) 和 (y) 为整数)构成了所有整数集合。这意味着我们可以用 (a) 和 (b) 的线性组合来表示任意整数。

4. 多个整数的扩展

裴蜀定理和欧几里得算法不止是适用于二元组,涉及多个整数的仍然成立。


请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值