zoukankan      html  css  js  c++  java
  • 欧几里得算法及其扩展

      先来看看欧几里得算法:

     1 public class Gcd {
     2     /**
     3      * 欧几里德算法,即辗转相除法 最大公约数
     4      */
     5     public static long gcd(long m, long n) {
     6         return n == 0 ? m : gcd(n, m % n);
     7     }
     8 
     9     /**
    10      * 最小公倍数lowest common multiple (LCM)
    11      * 最小公倍数 = a * b / a和b的最大公约数
    12      */
    13     private static long lcm(long a, long b) {
    14         return a * b / gcd(a, b);
    15     }
    16 }

      接着再来看裴蜀(贝祖)等式:对于任何整数a、b和它们的最大公约数d,关于未知数x和y的线性丢番图方程(称为裴蜀等式):ax+by = m 有整数解时当且仅当m是d的倍数。x、y可用扩展欧几里得算法求得。特别地,方程ax+by=1 有整数解当且仅当整数a和b互质。

      那什么是扩展欧几里得算法呢?

      现在我们知道了 a 和 b 的最大公约数是 gcd(a,b) 后面用gcd表示 ,那么,我们一定能够找到这样的 x 和 y ,使得: a*x + b*y = gcd 。这是一个不定方程。那么,怎么求出这个特解 x 和 y 呢?只需要在欧几里德算法的基础上加点改动就行了。我们观察到:欧几里德算法停止的状态是: a= gcd , b = 0 ,那么,这是否能给我们求解 x y 提供一种思路呢?

      首先,将a=gcd,b=0代入原方程,得到gcd*x+0*y=gcd。那么,这时候,只要x = 1 ,y 是 0 或者其他值(无所谓是多少,反正任何数乘以 0 都等于 0, 但是 x 一定要是 1),这时,我们就会有: a*1 + b*0 = gcd。 当然这是最终状态,但是我们是否可以从最终状态反推到最初的状态呢?

      假设当前我们要处理的是求出 a 和 b的最大公约数,并求出 x 和 y 使得 a*x + b*y= gcd ,而我们已经求出了下一个状态:b 和 a%b 的最大公约数,并且求出了一组x1 和y1 使得: b*x1 + (a%b)*y1 = gcd , 那么这两个相邻的状态之间是否存在一种关系呢?

      首先a可以表示成 a = b*t + k,而 t = a/b(这里的 “/” 指的是整除),k = a%b ,所以 可以得到a = b*(a/b) +k  -->  k=a-(a/b)*b  -->  a%b = a - (a/b)*b,代入 b*x1 + (a%b)*y1 = gcd。

      那么,我们可以进一步得到:gcd = b*x1 + (a-(a/b)*b)*y1
                       = b*x1 + a*y1 – (a/b)*b*y1
                       = a*y1 + b*(x1 – a/b*y1)

         对比之前我们的状态:求一组 x 和 y 使得:a*x + b*y = gcd ,是否发现了什么?

         这里: x = y1

               y = x1 – a/b*y1

      现在我们找到一组特殊的解  x0 和 y0,那么,我们就可以用 x0 和 y0 表示出整个不定方程的通解:

         x = x0 + (b/gcd)*t  ( t 取任意整数)

              y = y0 – (a/gcd)*t

      如果我们想要得到 x 大于 0 的第一个解的话,那么表达式就是:

        b /= d

        x = ( x0%b + b) % b

         以上就是扩展欧几里德算法的全部过程,依然用递归写:

     1 public class ExtGcd {
     2     static long x;
     3     static long y;
     4 
     5     public static long gcd(long m, long n) {
     6         return n == 0 ? m : gcd(n, m % n);
     7     }
     8     /**
     9      * 扩展欧几里得
    10      * 调用完成后 静态变量xy是ax+by=m的解
    11      * 返回的还是最大公约数
    12      */
    13     public static long ext_gcd(long a,long b){
    14         if (b==0) { // 求出了最大公约数 为a
    15             x = 1;
    16             y = 0;
    17             return a;
    18         }
    19         long res = ext_gcd(b, a % b);
    20         //x,y已经被下一层递归更新了
    21         long x1 = x;//备份x
    22         x = y;//更新x
    23         y = x1 - a / b * y;//更新y
    24         return res;
    25     }
    26     public static void main(String[] args) {
    27         System.out.println(ext_gcd(2, 7));  // 1
    28         System.out.println(x+" "+y);        // -3 1
    29     }
    30 }

      最后再来看一下这个线性方程(或者叫二元一次不定方程):ax+by = m 。有整数解时当且仅当m是gcd的倍数

      public static long linearEquation(long a, long b, long m) throws Exception {
        long d = ext_gcd(a, b);
        //m不是gcd(a,b)的倍数,这个方程无解
        if (m % d != 0) {
          throw new Exception("无解");
        }
        long n = m / d;//约一下,考虑m是d的倍数
        x *= n;
        y *= n;
        return d;
      }

      扩展欧几里德算法的应用主要有以下两个方面:

       (1)求解不定方程;

       (2)求解模线性方程(线性同余方程)与逆元;

  • 相关阅读:
    各国语言缩写列表,各国语言缩写-各国语言简称,世界各国域名缩写
    How to see log files in MySQL?
    git 设置和取消代理
    使用本地下载和管理的免费 Windows 10 虚拟机测试 IE11 和旧版 Microsoft Edge
    在Microsoft SQL SERVER Management Studio下如何完整输出NVARCHAR(MAX)字段或变量的内容
    windows 10 x64系统下在vmware workstation pro 15安装macOS 10.15 Catelina, 并设置分辨率为3840x2160
    在Windows 10系统下将Git项目签出到磁盘分区根目录的方法
    群晖NAS(Synology NAS)环境下安装GitLab, 并在Windows 10环境下使用Git
    使用V-2ray和V-2rayN搭建本地代理服务器供局域网用户连接
    windows 10 专业版安装VMware虚拟机碰到的坑
  • 原文地址:https://www.cnblogs.com/xiaoyh/p/10331666.html
Copyright © 2011-2022 走看看