• 乘法逆元


    首先附上学习的博客  https://blog.csdn.net/sdfzchy/article/details/76098066 
    https://blog.csdn.net/STcyclone/article/details/52081822
    相关 百科乘法逆元 https://baike.baidu.com/item/%E4%B9%98%E6%B3%95%E9%80%86%E5%85%83/5831857?fr=aladdin
    逆元 https://baike.baidu.com/item/%E9%80%86%E5%85%83%E7%B4%A0?fromtitle=%E9%80%86%E5%85%83&fromid=11054145
    同余方程 https://baike.baidu.com/item/%E5%90%8C%E4%BD%99%E6%96%B9%E7%A8%8B/9823007



    乘法逆元 至于我们为什么要讨论模意义下的运算呢
    ? 例如 1. 很多算法题的数值运算可能会溢出,为了研究和讨论算法,我们引入了模的概念 2. 哈希的时候,数值溢出是很正常的,所以我们需要通过取模,把哈希函数的数值限定在我们可控的范围内,让我们可以继续通过哈希的规则进行存放. 为什么需要乘法逆元 模意义下的加减乘运算都是具有封闭性的,但除法确是例外, 所以我们就要找一种在模意义下代替除法运算的东西. 即是说, 我们在模意义下的除法同一通过乘该数的乘法逆元来等价替代. 什么是乘法逆元呢? 定义: 在a,p互为质数的条件下, 如果 a * b 余 p 等于1 即 a * b % p == 1 则 我们称 b 是 mod p意义下a的逆元. 记作 b = inv(a) // 注, a * b 余 p 等于1 的通常写法时 a * b 同余 p == 1 例如: a / b % p 因为 模意义下是没有除法的. 但是我们可以转换成乘法做等价替换. 当a 与 p 互质时, a / b % p <==> a * inv(a) % p 同时 这也是我们通常取质数作为模数的原因(同时质数还有费马小定理,可以较快速的求出逆元.) // 另注: 其他: 关于同余方程 同余方程是一个数学方程式。 该方程式的内容为:对于一组整数Z, Z里的每一个数都除以同一个数m, 得到的余数可以为0,12,...m-1,共m种。 我们就以余数的大小作为标准将Z分为m类。每一类都有相同的余数。 那么 如果求解一个数的逆元呢. // 记得这个数和模数必须互质哟
    方法一:  扩展欧几里得 (求逆元 调用mod_reverse函数)
    // 限定条件 a n 互质  log(n)
    // @a 数
    // @n 模数
    inline long long mod_reverse(long long a,long long n)
    {
        long long x,y,d=extend_gcd(a,n,x,y);
        if(d==1) {
            if(x%n<=0)return x%n+n;  // 答案是负的要置为正的.
            else return x%n;
        } else return -1ll;
    }
    
    // 限定条件 a b 互质
    // @a 是 这个数  
    // @b 是 模数 
    // @x 是 返回的逆元 返回-1 表示没有逆元
    // @y 暂时不知道是什么...
    long long extend_gcd(long long a,long long b,long long &x,long long &y)
    {
        if(a==0&&b==0)
            return -1ll;
        if(b==0)
        {
            x=1ll;
            y=0ll;
            return a;
        }
        long long d=extend_gcd(b,a%b,y,x);
        y-=a/b*x;
        return d;
    }
    方法二:  费马小定理
    // 模数是一个质数 复杂度 log(n)
    // 原理, 当p是一个质数时,有 inv(a) = a^(p-2) % p;
    long long pwr4(long long a, long long k, long long jmod) {
        long long res = 1, base = a;
        while (k) {
            if (k&1)  res = res * base % jmod;
            base = base * base % jmod;
            k >>= 1;
        }
        return res;
    }
    
    long long mod_reverse(long long a, long long n) 
    {
        return pwr4(a, n-2, n);
    }
    方法三:  欧拉定理
    // 模数不是质数的情况
    // 由a^φ(p)≡ 1(mod p) 得 a^(φ(p)−1)是a的逆元 
    // φ(p)是欧拉函数
    // O(n)的时间可以递推出1~n在 mod p 意义下的逆元
    // 没用过 所以先给出别人的代码  kuangbin大神板子也有代码.
    void inv3(LL mod)//线性递推求逆元 
    {
        inv[1]=1;
        for(int i=2;i<=mod-1;i++)
        {
            inv[i]=(mod-mod/i)*inv[mod%i]%mod;
            cout<<inv[i]<<" ";
        }
    }
  • 相关阅读:
    函数响应式编程及ReactiveObjC学习笔记 (-)
    Flask的第一个应用
    Django错误 OperationalError: no such column: xxx
    Python高级数据类型模块collections
    wsgiref 源码解析
    WSGI文档(中文版)
    Python:树的遍历
    Django+haystack实现全文搜索出现错误 ImportError: cannot import name signals
    Django+Celery+Redis实现异步任务(发送邮件)
    Python面向对象—类的继承
  • 原文地址:https://www.cnblogs.com/cgjh/p/9425226.html
Copyright © 2020-2023  润新知