• something about 乘法逆元


    before 

    在求解除法取模问题(a / b) % m时,我们可以转化为(a % (b * m)) / b,
    但是如果b很大,则会出现爆精度问题,所以我们避免使用除法直接计算。
    (逆元就是倒数一样的东西吧??)

    可以使用逆元将除法转换为乘法:
      假设b存在乘法逆元,即与m互质(充要条件)。设c是b的逆元,即b * c≡1(modm),那么有a/b=(a/b)*1=(a/b)*b*c=a*c(%m)
      即,除以一个数取模等于乘以这个数的逆元取模。

    注意:在模意义下的加减乘运算都是具有封闭性的,但除法确是例外,所以我们就要找一种在模意义下代替除法运算的东西.

    乘法逆元定义  --  若正整数 a,b,p 满足a*b=1(% p),则a,b互为逆元,记b=inv(a)或b=a^(-1).

    比如说, 在模7 意义下,3 的乘法逆元是5, 也可以说模7 意义下5的乘法逆元是3.
       问: 模13 意义下5 的逆元是什么? asnwer:8
       问: 模6 意义下2 的逆元是什么? answer: .

    定理 -- (乘法逆元存在性定理)
    考虑同余方程:
                      ab ≡ 1(mod p)
      若a 与p 互质, 则一定存在一个正整数解b, 满 b < p.
      若a 与p 不互质, 则一定不存在正整数解b.
      意思也就是说, 互质与乘法逆元存在互为充要条件.
    证明:(ZL)

    now

    求解乘法逆元一般有三种方法:
      1.逆元求解一般利用扩展欧几里得。
      2.当p为质数的时候直接使用费马小定理,p非质数使用欧拉函数。
      3.当p为质数的时候,神奇的线性方法。

    首先来说一下扩展欧几里得求逆元

      对于一个数a,求其在 % p 下的逆元b,就是求ab ≡ 1(mod p)

      证明:

         上式变化:

            a * x + b * y = 1;
         由欧几里得有:
            gcd( a , b )=gcd( b , a % b );
         得
            a * x + b * y = b * x2 + (a % b) * y2;
         推得:
            a % b = a - a / b * b;
         将其代入原式化简得:
            a * x + b * y = b * x2 + ( a - a / b * b ) y2;
         所以:
            a * x + b * y = b * x2 + a * y2 - a / b * b * y2
            x = y2,y = x2 - a / b * y2;
         于是可以递归求解.
         易得当 b = 0 时,x = 1 ,y = 0 , 这也就是递归的边界.

     code

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

    然后费马小定理求解逆元

    费马小定理求解逆元(up):仅仅当p为质数的时.

      各种情况的证明

      TL1. 在p是素数的情况下,对任意整数x都有x^p≡x(mod)p。
      TL2. 如果x无法被p整除,则有x^(p-1)≡1(modp)。
      TL3. 可以在p为素数的情况下求出一个数的逆元,x*x^(p-2)≡1(modp),x^(p-2)即为逆元. 

      TL1.证明:
      首先强调p是素数
      那么将p次方拆开,用每个数 % p,将会得到一个 < = p 的数k ,k 的p次方的形式,由于p
      是一个质数,那么,k 如果 不是 1,它就一定与 p 互质,然后根据 费马小定理证明.
      ( x * x * x * x * x * x * x ) % 7 = ( y * y * y * y * y * y * y ) % 7
      TL2.证明:
      费马小定理正理
      TL3.证明:
      根据费马小定理 a ^ ( p - 1 ) = 1 ( % p ).

    综上我们可以知道代码就是快速幂嘛

    code

    int fast_pow(int x,int p)
    {
        int now=1;
        while(p)
        {
            if(p&1)
             {
                 now=now*x;
             }
             x=x*x;
             p>>=1;
        }
        return now;
    }

    最后神奇的线性求逆元

    ab = 1(mod p),求b

    p%a = p-(p/a)*a;  在c++中/为整除。

    (p/a)*a = p-(p%a);  换下位置

    (p/a)*a = -(p%a);  在模p意义下p可以约掉,可以没有这一步

    a = -(p%a)/(p/a);  再换一下位置

    a-1 = -(p%a)-1*(p/a);

    所以a-1可以用(p%a)-1推出,所以就可以用递推式来推出1到a的所有数的逆元。

    code

    int inv[1000];
    void INV(int a,int p)
    {
        inv[1] = 1;
        for (int i=2; i<=a; ++i)
            inv[i] = (-(p/i))*inv[p%i]%p;
    }

      同时间思考下可以通过上述方法递归求解一个数的逆元

    int INV(int a)
    {
        if (a==1) return 1;
        return ((-(p/a)*INV(p%a))%p);
    }

    IMPORTANT:欧拉函数求解逆元

    请参考:http://blog.csdn.net/yukizzz/article/details/51105009

    欧拉函数:

    ϕ(m)表示小于等于m且与m互素的正整数的个数。 
    如果x和m互质,则有xϕ(m)1(modm),即x×xϕ(m)11(modm),xϕ(m)1即为x的逆元。 
    m为质数的情况下,ϕ(m)=m1,即为费马小定理。

    代码:

    关键是求出欧拉函数的值。 
    利用欧拉函数的积性性质

    对于任意整数n,可以将它分解n=pk11pk22pk33...pkmm,其中pi为质数。

    其中ϕ(n)=ϕ(p1k1)ϕ(pk22)...ϕ(pkmm)

    最后转化为ϕ(n)=n(pi1)/pi

    对给定n进行整数分解。时间复杂度O(n√)。

    int eurler_phi(int n)
    {
        int res = n;
        for(int i = 2; i * i <= n; i++){
            if(n % i == 0){
                res = res / i * (i - 1);
                while(n % i == 0) n /= i;
            }
        }
        if(n != 1) res = res / n * (n - 1);
        return res;
    }

    筛法求欧拉函数值的表,利用埃氏筛法,每次发现质因子就把他的倍数的欧拉函数乘上(p1)p。 
    ACdreamers博客里介绍,利用定理进行优化 
    【update】这个定理是有用的,但是个人觉得他对偶数预处理的写法并没有啥用

    code

    int euler[maxn];
    void euler_phi2()
    {
        for(int i = 0; i < maxn; i++)  euler[i] = i;
        for(int i = 2; i < maxn; ++i){
            if(euler[i] == i){
                for(int j = i; j < maxn; j += i){
                    euler[j] = euler[j] / i * (i - 1);
                }
            }
        }
    }

    当n为奇数时,有ϕ(2n)=ϕ(n)

    因为2n是偶数,偶数与偶数一定不互素,所以只考虑2n与小于它的奇数互素的情况,则恰好就等于n的欧拉函数值。

  • 相关阅读:
    如何利用python制作微信好友头像照片墙?
    机器学习入门路线和资源
    突然“被辞职”的时候,原来可以拿到这么多钱!
    一个致命的 Redis 命令,导致公司损失 400 万
    程序员:想知道你每天按了多少次键盘吗?
    想了解真实的中国历史吗?建议看看这10部历史纪录片,受益终生!
    SpringBlade 2.0-RC3 发布,全新的微服务开发平台
    Syncd-开源自动化部署工具
    学习Spring Boot看这两个开源项目就够了!非得值得收藏的资源
    大型视频直播平台架构由浅入深详细讲解
  • 原文地址:https://www.cnblogs.com/shandongs1/p/7757987.html
Copyright © 2020-2023  润新知