• 初学 快速幂 的理解


      博客停了差不多三个月, 虽然这一段时间在学算法, 但从来没有写博客。 今天看了一上午的快速幂,突然想写写博客, 增加一下自己的记忆!这个博文知识简单介绍一下算法中取余的原因


     

     1 至于快速幂的概念不详细记录了。当我们想求a的b次幂对c取余时,我们会直接想到用这个算法:

    int ans = 1;
    
      for( i  = 1; i <= b; i++)
    
      {
    
        ans = ans * a;
    
      }
    
      ans %= c;

      这个算法的时间复杂度体现在for循环中,为O(b).这个算法存在着明显的问题,如果a和b过大,很容易就会溢出。因此需要用到离散数学知识(该知识点我也没学过,度娘教的^_^)


     

     

      定理1:

      

     


     

     2 由上面的公式可以推出: 

        

         把a看成 a * 1, 故由定理1可得出上面的公式。由此得到改进版本:

      int ans = 1; 
    
      a = a % c; //加上这一句
    
      for(int i = 1;i<=b;i++)
    
      {   
    
      ans = (ans * a) % c;//这里再取了一次余 
    
      } 
    
      ans = ans % c;

    这个算法在时间复杂度上没有改进,仍为O(b),不过已经好很多的,但是在c过大的条件下,还是很有可能超时,所以,我们推出以下的快速幂算法。


     

    3   快速幂算法依赖于以下明显的公式,我就不证明了,很简单理解。

      

        


    4    由此得到改进版本:

      int ans = 1;
    
      a = a % c;
    
       if(b%2==1) 
    
      ans = (ans * a) mod c; //如果是奇数,要多求一步,可以提前算到ans中
    
      k = (a*a) % c; //我们取a2而不是a
    
      for(int i = 1;i<=b/2;i++)
    
      { 
    
        ans = (ans * k) % c;
    
      } 
    
      ans = ans % c;

     

     5  我们可以看到,我们把时间复杂度变成了O(b/2).当然,这样子治标不治本。但我们可以看到,当我们令k = (a * a) mod c时,

       状态已经发生了变化,我们所要求的最终结果即为(k)^b/2 mod c而不是原来的a^b mod c,所以我们发现这个过程是可以迭代下去的。

     ((迭代就是把这一次算的值作为下一次循环的初始值,所以可以更简化该算法))

       当然,对于奇数的情形会多出一项a mod c,所以为了完成迭代,当b是奇数时,我们通过  ans = (ans * a) % c;来弥补多出来的这一项,

       此时剩余的部分就可以进行迭代了。   形如上式的迭代下去后,当b=0时,所有的因子都已经相乘,算法结束。于是便可以在O(log b)的时间内完成了。

       于是,有了最终的算法:快速幂算法。

     ((说实话, 我对这个简化有点糊涂,关于在O(log b)的时间内就可以完成, 就假装懂了吧, 以后慢慢理解吧))


     6

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

     


     

     

     7 将上述的代码结构化,也就是写成函数:

    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;
    
      }

     

      


     

     

          这就是最后的优化代码了。以上内容是抄袭的, 只不过自己又写了一遍。如果看不懂我写的的可以点下面网址:

      http://wenku.baidu.com/link?url=PdtuRuYTZSIfAC3TZCiHSx3fk7cEn3yuZBiYwbx-b7h_TOxNyOQtNOaUepEmxw56jhnPePqAdebOH6QL- pvmhFCYYdzGhYRneUM_oZTpxwO

       有关于快速幂的算法的推导,还可以从另一个角度来想。我就不介绍了。

  • 相关阅读:
    Saltstack module apache 详解
    Saltstack module ip 详解
    Saltstack module iosconfig 详解
    Saltstack module introspect 详解
    Saltstack module inspector 详解
    Saltstack module ini 详解
    Saltstack module incron 详解
    Modbus 指令 RS485指令规则
    停车系统对接第三方在线支付平台(二)
    停车系统对接第三方在线支付平台
  • 原文地址:https://www.cnblogs.com/lj-1568/p/4754336.html
Copyright © 2020-2023  润新知