• [数论]快速幂取模


    问题描述:

    已知底数a,指数b,取模值p,求 ab % p 的值


    朴素算法

    设初始值为1,循环b次,每次乘上a后再取模一下

    时间复杂度为O(n),虽然看着不高,但是一旦指数给得过大,肯定会TLE

    这里代码就不给出来了,就是一个简单的循环


    快速幂

    先不讨论取模,根据幂运算可知

    当b为偶数时:ab=a(b/2)*2=(a2)b/2

    当b为奇数时:ab=a*ab-1=a*(a2)(b-1)/2

    比如:28=44=162=256  直观一点:2*2*2*2*2*2*2*2=4*4*4*4=16*16=256

    比如:29=44*2=162*2=256*2=512  直观一点:2*2*2*2*2*2*2*2*2=4*4*4*4*2=16*16*2=256*2=512

    也就是每次将指数除以2,底数变为原来的平方,如果指数为奇数,则单独取一个出来另乘

    时间复杂度为O(logn)

     1 int pow_mod(int a,int b){
     2     int ans=1,base=a;
     3     while(b){
     4         if(b&1)//等价于判断奇偶
     5             ans*=base;
     6         base*=base;
     7         b>>=1;//将指数除以2
     8     }
     9     return ans;
    10 }

    快速幂取模

    由于幂的算术递增地非常快,long long也很容易超,这时候就需要取模一下,一般都是模以一个质数

    这时候我们需要了解数论中模运算的分配律:

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

    根据上述定理,我们还可以得到:

    ab % p = (a % p)b % p

    也就是指,在乘法中,模的顺序并不影响最后的结果

    然后我们就可以在做快速幂的过程中加上模运算

     1 int pow_mod(int a,int b,int p){
     2     int ans=1,base=a%p;
     3     while(b){
     4         if(b&1)//等价于判断奇偶
     5             ans=(ans*base)%p;
     6         base=(base*base)%p;
     7         b>>=1;//将指数除以2
     8     }
     9     return ans;
    10 }
    正因为是最弱,所以才理解智慧之强
  • 相关阅读:
    mysql分区
    pl/sql查看tnsnames.ora文件路径
    mysql之事务控制和锁定语句
    mysql返回查询行数fund_rows()
    mysql之视图
    Mysql之btree索引和hash索引的区别
    Java中反射 API 的使用
    zookeeper 客户端 Apache curator 分布式锁实操
    springBoot 整合 ZooKeeper Java客户端之 Apache Curator 实战
    初识 ZooKeeper
  • 原文地址:https://www.cnblogs.com/Yanick/p/11239817.html
Copyright © 2020-2023  润新知