zoukankan      html  css  js  c++  java
  • 快速幂取模详解与拓展

    紫书上同余与模算术一节关于此问题一笔带过,讲的不是很详细。

    本文原创,转载请注明出处 。:)

    问题定义:

    数论中经常出现的一个问题是对一个数的幂取模,也称为模取幂,即求a^b mod n。如果计算量较小,可以直接计算出a^b的值,再作模n运算。但是如果a和b的值都非常大,a^b的值用计算机难以表示,或者即使可以用大数运算的方式用计算机表示,也会因为耗时过长难以应用。基于模运算的基本性质,可以设计出一种算法,快速求解这一问题。这种方法为“快速幂取模”,也称为“反复平方法“。

    利用公式a*b%n=((a%n)*b)%n=((a%n)*(b%n))%n,可以先解决a^b可能太大存不下的问题

    d=ab mod n=(…((((a mod n)*a)mod n)*a)mod n…*a)mod n    {共b个a}

     由此可以引出一个迭代式

             d=a;

             for i=2 to b do  d=d mod n*a;

             d=d mod n;

     时间复杂度为O(b),当b很大时,效率很低。

    设b(i)指的是二进制下b的第i位,比如当b=13时,其二进制为1101,则b(2)表示0,b(1)表示1

    b = b(k) * 2^k + b(k-1)*2^(k-1) + ... + b(1) * 2^1 +b(0)*2^0 

    那么

    a ^ b = a ^ (b(k)*2^k + b(k-1)*2^(k-1) + ... + b(1)*2 + b(0) )

             = [a ^ (b(k)*2^k)]  * [a^(b(k-1)*2^(k-1))] *...*[a^(b(1)*2) ]* a

             = p(k) * p(k-1) * ... * p(1) * p(0)

    其中,p(i)=a ^ (b(i)*2^i),b(i)=1或是0,则p(i)=a ^ (2^i) 或者 p(i) = 1

    注意,p(i)可以一步一步的由前一个生成,即当p(i)=a ^ (2^(i-1)*2*b(i)),当p(i-1)!=0,b(i)!=0时,p(i)=p(i-1)*2

    那么此时结合公式a*b%n=((a%n)*b)%n

    p(i)%n=((p(i-1)%n)*b)%n

    a ^ b % n =( p(k) * p(k-1) * ... * p(1) * p(0) )%n

         =(…((((p(k) mod n)*p(k))mod n)*p(k-1))mod n…*p(0))mod n 

    结合上述迭代式,得到如下算法:

    int PowerMod(int a, int b, int c)
    {
    int ans = 1;
    a = a % c;
    while(b>0) {
    if(b % 2 == 1)
    ans = (ans * a) % c;
    b = b/2;
    a = (a * a) % c;
    }
    return ans;
    }

  • 相关阅读:
    Padding和父子继承宽高之间的关系
    Js实例——模态框弹出层
    Java——异常谜题
    BZOJ 2743 【HEOI2012】 采花
    BZOJ 4614 【WF2016】 Oil
    BZOJ 1004 【HNOI2008】 Cards
    codevs 2495 水叮当的舞步
    BZOJ 1227 【SDOI2009】 虔诚的墓主人
    BZOJ 3505 【CQOI2014】 数三角形
    BZOJ 4423 【AMPPZ2013】 Bytehattan
  • 原文地址:https://www.cnblogs.com/acbingo/p/4504381.html
Copyright © 2011-2022 走看看