zoukankan      html  css  js  c++  java
  • 【learning】 扩展欧几里得算法(扩展gcd)和乘法逆元

    有这样的问题:

    给你两个整数数$(a,b)$,问你整数$x$和$y$分别取多少时,有$ax+by=gcd(x,y)$,其中$gcd(x,y)$表示$x$和$y$的最大公约数。

    数据范围$a,b≤10^{18}$。

    求解这个问题有一种方法,叫做扩展欧几里得算法(简称扩欧),其本质是一个递归求解的过程。

    首先由一个前置的结论是$gcd(x,y)=gcd(y,x\%y)$。此处的$\%$为$c++$中取模操作,下同。

    我们不妨设$a>b$

    当$a≠0,b=0$时,则显然有$x=1,y=0$。此时$gcd(a,b)=a$。

    当$b≠0$时,我们假设我们已经求出了$bx'+(b\%a)y'=gcd(a,b)$的$x'$和$y'$(这是式1),我们现在要求的是$ax+by=gcd(a,b)$。

    我们对式子$1$做一些微小的变式

    原式$=bx'+(b\%a)y'$

    $=bx'+(a-lfloor frac{a}{b} floor imes b) imes y'$

    $=bx'+ay'-lfloor frac{a}{b} floor imes b imes y'$

    $=ay'+b(x'-lfloor frac{a}{b} floor y')$

    不难发现,$x=y'$,$y=(x'-lfloor frac{a}{b} floor y')$就是一组符合条件的解。

    然后无脑递归解决即可,代码很短,复杂度显然是$O(log_2 a)$的。

    1 void exgcd(int a,int b,int &x,int &y){
    2     if(!b) {x=1; y=0; return;}
    3     exgcd(b,a%b,y,x);
    4     y-=a/b*x;
    5 }

     

    下面来说下这东西能干啥

    我们不难发现,我们需要求$a$在模$b$意义下的乘法逆元(前提条件,$a$与$b$互质)

    我们可以执行一次$exgcd(a,b,x,y)$,然后$x$就是$a$在模$b$意义下的逆元。

    证明显然:

    $ax+by=1$

    $axequiv 1(mod b)$

    当模数不是质数的时候你就会知道这东西有多重要。

  • 相关阅读:
    安装jupyter_contrib_nbextensions库
    1.20
    架构之美阅读笔记01
    使用 netcat 数据源测试 Flume
    使用 Avro 数据源测试 Flume
    Tensorflow01-认识张量Tensor
    Spark06-RDD分区、缓存与Checkpoint讲解
    Spark05-RDD算子细谈
    Spark04-RDD入门
    Spark03-Scala面向对象和函数式编程
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10597049.html
Copyright © 2011-2022 走看看