• 欧几里得算法及其扩展学习笔记


    欧几里得算法

    在欧几里得著的《几何原本》里面,有用线段的划分来讲解这个数学方法的,这里我们从代数而不是几何上来讲,并且侧重于算法OI竞赛。

    欧几里得算法(gcdgcd),又称辗转相除法,可以用来快速计算两个整数的最大公约数,并有许多扩展应用。


    下面我们来看公式:
    gcd(n,m)=gcd(m,n mod m)gcd(n,m)=gcd(m,n m mod m)

    我们可以简单的证明一下这个公式的正确性:
    我们令g=gcd(n,m)g=gcd(n,m),那么显然gn,gmg|n,g|maba|b表示aabb的因子)。又因为n mod m=nm×nmn m mod m=n-m imes lfloorfrac{n}{m} floor,那么我们可以将n,mn,m写为n=k1g,m=k2gn=k_1g,m=k_2g,那么n mod m=nm×nm=k1gk2gk1gk2g=g(k1k2k1gk2g)n m mod m=n-m imes lfloorfrac{n}{m} floor=k_1g-k_2glfloorfrac{k_1g}{k_2g} floor=gleft(k_1-k_2leftlfloorfrac{k_1g}{k_2g} ight floor ight),而(k1k2k1gk2g)left(k_1-k_2leftlfloorfrac{k_1g}{k_2g} ight floor ight)肯定为整数,所以g(n mod m)g|(n m mod m),那么显然ggcd(m,n mod m)g|gcd(m,n m mod m),(因为ggn,mn,m的因子)。接下来我们令g^=gcd(m,n mod m)hat g=gcd(m,n m mod m),那么显然有g^ghat g|g,又因为前面我们可以得知gg^g|hat g,所以就有g=g^g=hat g,那么gcd(n,m)=gcd(m,n mod m)gcd(n,m)=gcd(m,n m mod m)

    所以代码就简单啦!
    递归边界为m=0m=0时,因为模数不能为0,所以此时就可以直接返回nn

    int gcd(int n,int m){
    	if(!m) return n;
    	else return gcd(m,n%m); 
    }//也可以用自带的__gcd(n,m);
    

    扩展欧几里得算法

    • 前置

    • 裴蜀定理(贝祖定理)

    内容:对于一个系数为整数(a,b,ca,b,c为整数)的二元一次方程ax+by=cax+by=c,若其存在整数解,当且仅当gcd(a,b)cgcd(a,b)|c
    用处:判断一个上述的二元一次方程是否有整数解。

    简单的证明:
    我们令g=gcd(a,b)g=gcd(a,b),同样的我们可以将a,ba,b写成a=k1g,b=k2ga=k_1g,b=k_2g,那么显然ax+by=g(k1x+k2y)ax+by=g(k_1x+k_2y),所以g(ax+by)g|(ax+by)

    所以当gcd(a,b)cgcd(a,b)|c时必然有整数解,下面我们将在扩展欧几里得算法讲解给出证明,及其整数解的求法。


    正题

    • Exgcd

    ax+by=cax+by=ccgcd(a,b)c|gcd(a,b)前提下是否一定有整数解呢?

    因为有了前提,所以我们可以将原式写成ax+by=kgcd(a,b)ax+by=kcdot gcd(a,b),由于kk为整数,那么如果ax+by=gcd(a,b)ax+by=gcd(a,b)有整数解,那么原式一定有整数解(倍数关系),那么只需证明并求出ax+by=gcd(a,b)ax+by=gcd(a,b)的一组特殊解(x1,y1)(x_1,y_1),然后所有的解都可以表示出来(原来的解就是现在解的kk倍)。

    所以现在我们只需证明ax+by=gcd(a,b)ax+by=gcd(a,b)有解即可。

    通过gcdgcd的递推式可知,我们如果的到如下式子的一组解:
    bx+(a mod b)y=gcd(b,a mod b)bx+(a m mod b)y=gcd(b,a m mod b)
    令解为(x1,y1)(x_1,y_1),那么就有如下推导:
    ax+by=bx1+(a mod b)y1ax+by=bx_1+(a m mod b)y_1
    =bx1+(aab×b)y1=bx_1+(a-leftlfloorfrac{a}{b} ight floor imes b)y_1
    =ay1+(x1aby1)b=ay_1+(x_1-leftlfloorfrac{a}{b} ight floor y_1)b
    一个小引理当ax+by=az+bkax+by=az+bk,必然x,yx,y有一组解为x=z,y=kx=z,y=k
    ax+by=ay1+(x1aby1)bax+by=ay_1+(x_1-leftlfloorfrac{a}{b} ight floor y_1)b
    所以有一组解为x=y1,y=x1aby1x=y_1,y=x_1-leftlfloorfrac{a}{b} ight floor y_1,而这个解显然一定会满足ax+by=gcd(a,b)ax+by=gcd(a,b)。所以我们不仅证明了它一定有解,还构造出了解的样子和求法。
    代码就是这样的:

    int exgcd(int a,int b,int &x,int &y){
    	if(!b){x=1;y=0;return a;}
    	else {int now=exgcd(b,a%b,y,x);y-=x*(a/b);return now;}
    }	
    

    递归边界显然就是当ax+by=gcd(a,b)ax+by=gcd(a,b)的时候,b=0b=0,显然gcd(a,b)gcd(a,b)不合法,所以我们就令gcd(a,0)=agcd(a,0)=a,那么原来方程就变为ax=aax=a,显然x=1,y=0x=1,y=0

    辗转相减的用途

    既然有更快的辗转相除,那么辗转相减有什么用呢?
    我们知道gcd(a,b)=gcd(a,ba)gcd(a,b)=gcd(a,b-a),那么容易推广而知gcd(a1,a2,a3, ,an)=gcd(a1,a2a1,a3a2, ,anan1)gcd(a_1,a_2,a_3,cdots ,a_n)=gcd(a_1,a_2-a_1,a_3-a_2,cdots,a_n-a_{n-1}),那么对于一个序列aa的区间gcdgcd,我们可以通过差分的方式快速维护。
    题目:bzoj 5028 小Z的加油店

    应用

    • 求乘法逆元

    因为我们可以发现,逆元式子ax1( mod m)axequiv 1( m mod m)xx为逆元,当gcd(a,m)=1gcd(a,m)=1,它可以写成ax=1+bmacdot x=1+bcdot m,也就是ax+(b)m=1acdot x+(-b)cdot m=1,因为gcd(a,m)1gcd(a,m)|1,所以我们用扩展欧几里得算法求出这个方程的一组解,其中的xx便是它的逆元。友链-逆元求法

    • 求方程的一组解(基本操作)

    • 辗转相除法神奇用法:求以下式子
      i=1ni×pqsum_{i=1}^{n}leftlfloorfrac{i imes p}{q} ight floor
      具体为转换成三角形求内部整点个数。

    • 题目1

    • 题目2

    推荐这个讲解的友链文章IN


  • 相关阅读:
    Vue 2.x windows环境下安装
    VSCODE官网下载缓慢或下载失败 解决办法
    angular cli 降级
    Win10 VS2019 设置 以管理员身份运行
    XSHELL 连接 阿里云ECS实例
    Chrome浏览器跨域设置
    DBeaver 执行 mysql 多条语句报错
    DBeaver 连接MySql 8.0 报错 Public Key Retrieval is not allowed
    DBeaver 连接MySql 8.0报错 Unable to load authentication plugin 'caching_sha2_password'
    Linux系统分区
  • 原文地址:https://www.cnblogs.com/VictoryCzt/p/10053430.html
Copyright © 2020-2023  润新知