• 数论——乘法逆元(快速幂求法)及模运算


    一、快速幂

    原理:

      快速幂的原理十分简单。

      ak=a2^0*a2^1*a2^2*…a2^x,其中k=20+21+22+…+2x

      这显然是正确的。因为任何一个数都可以表示成二进制。

      接下去利用位运算实现即可。

    代码实现

      模板题链接:快速幂

      代码模板如下:时间复杂度O(logk)

    int qmi(int a,int k,int p)
    {
        int res=1%p;
        while(k)
        {
            if(k&1)res=(long long)res*a%p;
            a=(long long)a*a%p;
            k>>=1;
        }
        return res;
    }

      值得一提的是,以上代码在过程中取模,是基于模运算的运算规则。

      模运算有一些很好的性质,以下列举四条:

    •  (a + b) % p = (a % p + b % p) % p 
    •  (a - b) % p = (a % p - b % p + p) % p 
    •  (a * b) % p = (a % p * b % p) % p 
    •  (a^b) % p = ((a % p)^b) % p 

    二、快速幂求逆元

    乘法逆元的定义

     若整数b,m互质,并且b|a,则存在一个整数x,使得a/bax(mod m),则称x为b的模m乘法逆元,记为b1(mod m)

    b存在乘法逆元的充要条件是b与模数m互质。当模数m为质数时,bm2即为b的乘法逆元。

      因为在模运算中,并没有除法的性质,即没有(a/b)%p≠((a%p)/(b%p))%p,而乘法逆元便可以帮助我们将其转化成乘法形式:a/b % m=ax % m。

      由乘法逆元的定义我们可以推出如下结论:

    ∵ a/b mod p = a * b-1 mod p = a/b * b * b-1 mod p

    ∴ b * b-1 ≡ 1(mod p)

    费马小定理

    若p是一个质数,且整数a不是p的倍数(a与p互质),则有a p-1 ≡ 1(mod p)。

      基于这个定理,我们就可以推出如下结论:

     ∵ a p-1 ≡ 1(mod p)

    ∴ a * a p-2 ≡ 1(mod p)

      因此,结合乘法逆元的定义所得到的推论以及费马小定理,我们可以得到:a-1 = a p-2(mod p)。

      也就是说,当模数p为质数,且整数b不是p的倍数时(b与p互质),b的逆元即为b p-2

    代码实现

      模板题链接:快速幂求逆元  

      根据上述结论,要判断b关于模数p的乘法逆元是否存在,若存在则求出之,我们便只需要计算b p-2即可。而这个计算利用快速幂便可以很快解决。

      代码如下:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    
    int qmi(int a,int k,int p)
    {
        int res=1%p;
        while(k)
        {
            if(k&1)res=(ll)res*a%p;
            a=(ll)a*a%p;
            k>>=1;
        }
        return res;
    
    }
    
    int main()
    {
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(a%b==0)printf("impossible
    ");
            else printf("%d
    ",qmi(a,b-2,b));
        }
        return 0;
    }

    应用

      有了乘法逆元,我们在计数类问题中遇到(a/b)%p时,便可以转化成((a % p) * (b-1 % p)) % p来计算了,这样便防止了爆int的情况出现,当然,转化的前提是必须保证b与p互质。当p是质数时,则可以进一步转化为((a % p) * (b p-2 % p)) % p。

  • 相关阅读:
    java面向对象类的继承~ 匿名类 ;多态特性;强制类型转换
    Java面向对象~类和对象&方法,类方法
    1036. Escape a Large Maze
    909. Snakes and Ladders
    559. Maximum Depth of N-ary Tree
    987. Vertical Order Traversal of a Binary Tree
    913. Cat and Mouse
    865. Smallest Subtree with all the Deepest Nodes
    882. Reachable Nodes In Subdivided Graph
    864. Shortest Path to Get All Keys
  • 原文地址:https://www.cnblogs.com/ninedream/p/11215360.html
Copyright © 2020-2023  润新知