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


 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而不是afor(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

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

转载于:https://www.cnblogs.com/lj-1568/p/4754336.html

初学 快速幂 的理解相关推荐

  1. 数论基础之快速幂(详细教程)

    2020.2.17更新,将模板改为c++版,以及增加了对循环版快速幂的理解 一.问题引入 求 anmodpa^n \ mod \ pan mod p 的结果 分析 思路:看到这样的题目,我们最容易想到 ...

  2. hdu 2035 人见人爱A^B (快速幂)

    人见人爱A^B Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  3. 矩阵的乘法和快速幂的一些理解(适用初学者)

    矩阵是线性代数的知识...后悔没好好学了... 第一部分:矩阵的基础知识 1.结合性 (AB)C=A(BC). 2.对加法的分配性 (A+B)C=AC+BC,C(A+B)=CA+CB . 3.对数乘的 ...

  4. 快速幂实现pow函数(从二分和二进制两种角度理解快速幂)

    文章目录 迭代实现快速幂 思路 int的取值范围 快速幂 从二进制的角度来理解 从二分法的角度来理解 代码 复杂度分析 进阶--超级次方 思路 倒序+快速幂 正序+快速幂 代码 复杂度分析 迭代实现快 ...

  5. 快速幂(二进制理解)

    一.题目背景 已知底数a,指数b,取模值mod. 求ans = a^b % mod 二.朴素算法(已知可跳过) ans = 1,循环从 i 到 b ,每次将 ans = ans * a % mo 时间 ...

  6. 矩阵快速幂求斐波那契数列(初学整理)

    参考文章: http://blog.csdn.net/u013795055/article/details/38599321 http://blog.csdn.net/g_congratulation ...

  7. 快速幂算法(理解快速幂只需两道题)

    重点看代码注释 题目 2088: [蓝桥杯]快速幂 时间限制: 1Sec 内存限制: 128MB 题目描述 给定A, B, P,求(A^B) mod P. 输入 输入共一行. 第一行有三个数,N, M ...

  8. 完全理解乘法快速幂及其两种写法的解析

    an=?0≤n≤10105an=?0≤n≤10105 a^n=? \qquad 0 \le n \le 10^{10^5} 没错,乘法快速幂就是解决上述问题的. 乘法快速幂的思想 可以看到,要求一个数 ...

  9. LeetCode50——一题学会快速幂算法

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode的第31篇文章,我们来看下LeetCode的第50题,求一个数的幂. 题意 这道题的题意只有一句话,就是给定两个数x和 ...

最新文章

  1. 测试与封装5.1.5.2
  2. 数据结构 -- 散列表
  3. Hbase的过滤器查询
  4. Listener监听器之HttpSessionListener
  5. [Android]ListView性能优化之视图缓存
  6. php+mysql 大容量数据高效分页效果(弃用limit)
  7. bzoj1607: [Usaco2008 Dec]Patting Heads 轻拍牛头
  8. commons-fileupload 图片上传示例
  9. 芦溪中学2021高考成绩查询,三台县芦溪中学2021年招生简章
  10. 中国什么时候才能全面普及 1 Gbps 下行的网速?
  11. 第九章 单处理器调度
  12. grep, egrep
  13. mongodb java 开源_开源的Mongodb java client -- mango发布
  14. mysql sqlserver alter语句区别_SQL ALTER
  15. brave浏览器_升华拜克股票行情:Brave推出适用于PC和移动设备的以隐私为中心的广告拦截浏览器v1.0...
  16. Selenium 方法封装 一
  17. VS2010 C# 调用Web Service
  18. Linux中的用户切换:su和su - 的区别
  19. python 知乎接口_ZhihuVAPI 是一个可以让你以一种优雅的形式调用知乎数据的 Python 包....
  20. NTFS, FAT32和exFAT文件系统有什么区别

热门文章

  1. 设置mysql表名不区分大小写
  2. elementui 单独修改一个label的样式
  3. Java终止线程的三种方式
  4. Android开发笔记(一百六十)休眠模式下的定时器控制
  5. 前端后台与接口的问题
  6. Java Platform SE 8 中文文档
  7. 报错--Problem executing scripts APT::Update
  8. iOS开发笔记系列-基础3(多态、动态类型和动态绑定)
  9. 棋牌游戏服务器架构: 详细设计(3) 数据库设计
  10. bzoj15523506 robotic sort