zoukankan      html  css  js  c++  java
  • 求逆元

    数论倒数,又称逆元

    先讲求余的概念:

    (a + b) % p = (a % p + b % p) % p  (对)

    (a - b) % p = (a % p - b % p) % p  (对)

    (a * b) % p = (a % p * b % p) % p   (对)

    (a / b) % p = (a % p / b % p) % p     (错)

    为什么除法是错的呢?

    举个例子: (100/50) % 20 = 2   !=   (100%20)/(50%20) % 20 = 0

    对一些题目,我们需要在中间进行求余运算,否则数据太大可能会爆!那么是不是这个算式中出现了除法,那么我们就无法运算了呢?

    当然不是!!

    这个时候就需要逆元了!

    我们知道

    如果

    a*x = 1

    那么x是a的倒数,x = 1/a

    但是a如果不是1,那么x就是小数

    那数论中,大部分情况都有求余,所以现在问题变了

    a*x  = 1 (mod p)

    那么x一定等于1/a吗

    不一定

    所以这时候,我们就把x看成a的倒数,只不过加了一个求余条件,所以x叫做    a关于p的逆元

    比如2 * 3 % 5 = 1,那么3就是2关于5的逆元,或者说2和3关于5互为逆元

    这里3的效果是不是跟1/2的效果一样,所以才叫数论倒数

    a的逆元我们用inv(a)表示

    a和p互质,a才有关于p的逆元

    那么(a/b)%p = (a * inv(b)) % p = (a % p * inv(b) % p) % p

    逆元已经介绍清楚了,那么如何去求逆元呢?

    方法一:

    利用费马小定理

    a^(p-1) ≡1 (mod p)

    推导出:

    inv(a) = a^(p-2) (mod p)

    再运用下我们之前提过的快速幂!

    注意一下有求inv(a) 的前提是a和p互质

    LL pow_mod(LL a, LL b, LL p){//a的b次方求余p 
        LL ret = 1;
        while(b){
            if(b & 1) ret = (ret * a) % p;
            a = (a * a) % p;
            b >>= 1;
        }
        return ret;
    }
    LL Fermat(LL a, LL p){//费马求a关于b的逆元 
            return pow_mod(a, p-2, p);
    }

    方法二:

    利用扩展欧几里得

    a*x + b*y = 1

    如果a,b互质,有解

    则这个解的x 就是 a关于b的逆元

         y 就是 b关于a的逆元

    简单的推导一下吧:

    先两边%b:  a*x%b = 1 % b

           a*x = 1 (mod b)

    所以 x 是 a关于b的逆元 

    void ex_gcd(LL a,LL b,LL &x,LL &y,LL &d)
    {
        if(b==0)
        {
            x=1;
            y=0;
        }
        ex_gcd(b,a%b , y, x, d);
        y -= (a/b)*x;
    }
    
    LL inv(int t , int p)
    {
        LL d, x ,y;
        ex_gcd(t, p, x, y, d);
        return d == 1 ? (x % p + p) % p : -1;
    }

    方法三:

    利用递归的方式求逆元

    当p是一个质数的时候有

    inv(a) = (p - p / a) * inv(p % a) % p

    一直递归到1为止,因为1的逆元就是1

    LL inv(LL t, LL p) {//求t关于p的逆元,注意:t要小于p,最好传参前先把t%p一下 
        return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p;
    }

    参考:https://www.cnblogs.com/linyujun/p/5194184.html

  • 相关阅读:
    Job for docker.service failed because the control process exited with error code. See
    连接数据库出现The server time zone value '�й���׼ʱ��' is unrecogni等问题的解决方案
    【面试】SSH 框架原理
    【面试】Spring 执行流程
    【面试】Redis
    Innosetup打包自动下载.net framework 动态库及替换卸载程序图标.
    分享一个带有合计行功能的DataGridView扩展
    记录一次系统优化
    使用 Cordova(PhoneGap)构建Android程序
    分享一个换肤解决方案
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/11062340.html
Copyright © 2011-2022 走看看