ACM算法:快速幂取模(详细)
来源:互联网 发布:网络4大粪坑 编辑:程序博客网 时间:2024/06/05 19:56
快速幂取模的用途:在ACM这类竞赛中,可能会遇到指数型的数据取模问题,这个时候如果直接用int或者long long储存,就
有可能会超出计算机整数的存取范围,而导致数据出错。所以我们需要一种方法进行计算。而这种方法就是我们这次要讲到
的快速幂取模(简称快速幂)。这种算法在时间和空间上都做了尽可能的优化,所以学会之后,会觉得非常好用。
快速幂取模的思路:快速幂实现的最基本的理论就是我们离散课上或者数论中学过的一条公式推出的引理。
引理:积的取余等于取余的积的取余。
再在这条引理的基础之上,对指数型数据进行拆分以及合并,从而得到我们用的快速幂算法。
本文我就不用例题讲解,直接对快速幂进行解析。毕竟快速幂的算法相对简单,而且适用题型较为一致。
快速幂具体分析:对a^b进行分析。
对于当a和b较小是直接用int或者long存是没有问题的,但是当a和b大到一定程度时,这就不是暴力存就
可以解决的问题了。我们应该怎么去解决这个问题呢?
在这里我们需要把注意力放在“大”字上面,正是由于a和b过大才导致的问题。所以我们要想办法不断地减
小a和b的规模,所谓逐个击破。
根据上面的那条引理,我们知道了可以把指数拆开,从这个突破口突破。这里我们就不难想到这样一个算法:
//①a是底数,b是指数,mode是取模数,sum是记录取模的结果int sum = 1;a = a % mode; for(int i = 1; i <= b; i++){sum = sum * a;}sum = sum % c;
这是直接利用的 引理而写出来的代码,这只是单纯的降低的a的规模,但是这还达不到我们的要求,所以我们
需要进一步改进算法。(当然还可以继续降低啊的规模,即将循环中的那句换成sum = (sum * a)%mode)
我们已经实现的降低a的规模,所谓我们要想着怎么降低b的规模。我们首先看两个样例:先看b为偶数的样例
7^16,mode = 3,我们要怎么进行拆分?
最基本的拆分是这样的:7*7*7*7*7*7*7*7*7......7,上面的算法只是将其变为2*2*2*2*2*2*2......2,那么怎么减少b
的规模呢?你应该有一点感觉了吧。就是两两合并,将(7^16)变成(49^8),这就降低了b的规模,再利用上面
的算法降低a的规模,最终会变成1 *1*1*1*1*1*1*1。是不是感觉整个数简单了很多。
按照这个思路,我们可以多循环几次,从而不断的降低a和b的规模。
那么b为奇数怎么办呢?
其实也很简单,我们只要在偶数算法的基础之上,每次把多出来的这个数跳出来,预先取模再带入即可。
从而最终得出快速幂的代码:
long long Mode(long long a, long long b, long long mode){long long sum = 1;a = a % mode;while (b > 0) {if (b % 2 == 1)//判断是否是奇数,是奇数的话将多出来的数事先乘如sumsum = (sum * a) % mode;b /= 2;a = (a * a) % mode;// 不断的两两合并再取模,减小a和b的规模}return sum;}
当然有时候你可能会碰到用&的运算符的代码实现,其实和这个大致相同,只不过是用&操作符对b的奇偶性进行判断而已
&的操作符:二进制位中,1 & 1 = 1,其余组合均为0
附上用&实现的代码:
long long Mode(long long a, long long b, long long mode){long long sum = 1;while (b) {if (b & 1) {sum = (sum * a) % mode;b--;}b /= 2;a = a * a % mode;}return sum;}
总结:快速幂虽然是个“小”算法,但是有需要用到它的时候非常有用,所以不能小看它,只要稍加功夫去理解,快速幂
还是很好学的,当然一切都需要你在题目中得到锻炼。
- ACM算法:快速幂取模(详细)
- ACM算法:树状数组(详细)
- ACM 算法详细分类
- ACM算法详细分类
- 快速最优通道布线算法(详细)
- acm-最大公约数/最小公倍数 快速算法
- FOCR:快速最优通道布线算法(详细)
- ACM算法——快速排序
- ACM基础算法复习(STL + DFS + BFS + 并查集 + 快速幂 + 欧几里得算法)
- 小学生学ACM----快速幂取模
- python算法--快速排序详细实现
- java 快速排序递归算法详细解析
- 快速排序算法详细讲解c++版
- hdu5972 快速匹配bitset优化(shiftand算法)2016ACM/ICPC亚洲区大连站
- ACM从零开始---电子科大POJ "快速排序算法"
- 快速幂&快速幂取模算法
- C语言实现数组快速排序(含对算法的详细解释)
- C语言实现数组快速排序(含对算法的详细解释)
- HDU1274 展开字符串
- 深入理解Java对象的创建过程:类的初始化与实例化
- MySQL约束及相关操作
- CCF 火车购票(Java)
- LintCode:M-逆波兰表达式求值
- ACM算法:快速幂取模(详细)
- PHP 开发者该知道的 5 个 Composer 小技巧
- 关于技术团队的建设
- spring之JDBC
- 网络通信概述
- 黑盒测试和白盒测试
- java 在主程序中添加和引用自定义程序的两种方法(主类中的static方法和其他类中的普通方法)
- NI PXIE6259接线说明
- UFT-b/s常用对象WebList,WebRadioGroup,WebTable