【OI】关于快速幂的简单理解
都知道算某个数的幂需要线性的复杂度,为了优化复杂度,就出现了所谓的快速幂。
快速幂的代码很短,但是要原理需要一点心思。
首先,我们知道,
a^b = a^c * a^d (c+d=b)
那么,不就可以通过 a^b = a^b1 * a^b2 * a^b3... * a^bn (b1 + b2...+bn = b) 来快速获得a^b吗?这个方法的优越性在于,如果可以线性的求出a^b1~a^bn,不就是很快的算法吗?
因为a^b=a^c*a^d,c+d=b这条原理,我们的目标是找到普遍满足 b = b1 + b2 ... + bn的规律。所以,我们必须要找出一个统一的方法来确定b对应的b1~bn分别是多少。
如果各位知道进制转换的原理,就可以知道:一个n进制的数转为十进制等于 求和( i = 0~n-1 ) n ^ i * 第 i 位的数字。
例如,十进制数10的二进制数1010可以表示为: 2^0 * 0 + 2^1 * 1 + 2^2 * 0 + 2^3 * 1 (这里挺绕的,为了方便理解和验证,2^3*1意思是 2进制,第3位,二进制数字1010中第三位是1)
仔细一想,这不就是我们要的"确定b对应的b1~bn分别是多少"吗?这也是快速幂的原理所在,将一个质数分解为许多可以线性一个个求出的2的次方的幂。
我再次重申a^b=a^c*a^d,c+d=b这条原理,不能不搞清楚乘法和加法的关系,我们之前得到的加法规律实际上是应用于c+d=b这里的,最后的计算还是要用乘法。
之前我一直在说,这个方法或者说规律的优越性在于我们可以线性的求出相加的每一个指数。
例如,我知道十进制数10,也就是二进制数1010,我就可以在线性时间复杂度里得到 2^0 * 0 、 2^1 * 1 、 2^2 * 0 、 2^3 * 1。
说了这么多废话,目的在于接下来的这一条原理。
( a^(2^0) )^2 = a^(2^1) 你可以亲自验证一下这条神奇的性质。不仅是对0+1 = 1有效,你可以把0换成任何一个数,把1换成那个数+1,看看还会不会生效。
对于每个数k,归纳一下,就是 (a^(2^k) )^2 = a^(2^(k+1) ) 。其实自己稍微一想,就明白是怎么回事了。
typedef long long ll;
ll poww(ll a, ll b)//a^b
{
ll re = ;
while(b != )
{
if(b & )
re *= a;
a = a * a;
b >>= ;
}
return re;
}
解释一下代码。
b & 1代表着我们之前的判断"为了不让它“滥竽充数”地也来分一杯羹,我们使用&运算符,判断这个二进制最后一位是否为0"。为什么要判断“最后一位”,因为我们在判断完指数的二进制的某一位后,那一位不再有用,
所以我们使用 b >>= 1也就是位运算符「右移」来消除使用过的那一位。由于我们不想计算当前是哪一位,并且希望代码尽可能的简便高效,我们只能不计当前是多少位,
用之前说过的利用平方来求下一个b1~bn中的一个。(b=Σ(i=1~n) bi,Σ为求和,求b1+.2+...bn,我有点啰嗦,但能让更多人看懂)。
所以,为了简洁高效地完成任务,实际上我们把原来的 一个n进制的数转为十进制等于 "求和( i = 0~n-1 ) n ^ i * 第 i 位的数字” 变成了 “ 求和( i = 0~n-1 ) n ^ i ”。
例如,十进制数10的二进制数1010按照我们原来的方式是: 2^0 * 0 + 2^1 * 1 + 2^2 * 0 + 2^3 * 1,而在代码里是 2^0 + 2^1 + 2^2 + 2^3
这就不可避免的造成了在某个数的二进制的某一位是0而造成本该是0的指数被我们计算成了别的数。所以,我们一定要在一开始加上二进制下最后一位是否为0的条件,如果不是0那么就可以把当前得到的结果乘到我们的最终结果变量上,如果是0则不能乘到最终结果变量上,但是a依然要平方,不能因为这一位数字的结果被忽略而不计下一位数字的结果应当按照我们之前的方法线性求出本当乘上的数字。(例如,按照我们之前1010的例子,2^0 * 0被我们忽略,但是如果上一位数字的结果被忽略就不考虑下一位的话,这一位的指数就是2^0*1了,与我们期待的结果不符。)
说了这么多,发现自己想说的其实可以精炼一下,把自己的思考过程部分隐去。但是转念一想,对于第一次听说线性筛的OIer或者别的学习者需要详细的描述,而我自己也不能保证一直记住快速幂的原理,权当整理了。
如果本篇博客有差错或者不恰当之处,请多多指正。
【OI】关于快速幂的简单理解的更多相关文章
- hdu 1575 Tr A(矩阵快速幂,简单)
题目 和 LightOj 1096 - nth Term 类似的线构造一个符合题意的矩阵乘法模版,然后套快速幂的模版,具体的构造矩阵我就不作图了,看着代码也能理解吧 #include<stdi ...
- hdu 1757 A Simple Math Problem (矩阵快速幂,简单)
题目 也是和LightOJ 1096 和LightOJ 1065 差不多的简单题目. #include<stdio.h> #include<string.h> #include ...
- zoj 2974 Just Pour the Water (矩阵快速幂,简单)
题目 对于案例的解释请见下图: 这道要变动提取一下矩阵,之后就简单了 具体解释可看代码: #include <string.h> #include <stdio.h> #inc ...
- LightOj 1065 - Number Sequence (矩阵快速幂,简单)
题目 和 LightOj 1096 - nth Term 差不多的题目和解法,这道相对更简单些,万幸,这道比赛时没把模版给抽风坏. #include<stdio.h> #include&l ...
- LightOj 1096 - nth Term (矩阵快速幂,简单)
题目 这道题是很简单的矩阵快速幂,可惜,在队内比赛时我不知什么时候抽风把模版中二分时判断的 ==1改成了==0 ,明明觉得自己想得没错,却一直过不了案例,唉,苦逼的比赛状态真让人抓狂!!! #incl ...
- hdu 1757 (矩阵快速幂) 一个简单的问题 一个简单的开始
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1757 题意不难理解,当x小于10的时候,数列f(x)=x,当x大于等于10的时候f(x) = a0 * ...
- poj 3070 Fibonacci(矩阵快速幂,简单)
题目 还是一道基础的矩阵快速幂. 具体的居者的幂公式我就不明示了. #include<stdio.h> #include<string.h> #include<algor ...
- 矩阵快速幂/矩阵加速线性数列 By cellur925
讲快速幂的时候就提到矩阵快速幂了啊,知道是个好东西,但是因为当时太蒟(现在依然)没听懂.现在把它补上. 一.矩阵快速幂 首先我们来说说矩阵.在计算机中,矩阵通常都是用二维数组来存的.矩阵加减法比较简单 ...
- (快速幂)51NOD 1046 A^B Mod C
给出3个正整数A B C,求A^B Mod C. 例如,3 5 8,3^5 Mod 8 = 3. Input 3个正整数A B C,中间用空格分隔.(1 <= A,B,C <= 10^ ...
随机推荐
- 小程序调用支付报错:jsapi缺少参数: total_fee
这种情况通常是因为在调用的时候,package参数有问题导致: wx.requestPayment中package参数必须是package:"prepay_id=wx21********** ...
- 邮箱地址自动提示jQuery插件
// mailAutoComplete.js v1.0 邮箱输入自动提示// 2010-06-18 v2.0 使用CSS class类代替CSS对象,同时增强代码可读性// 2010-06-18 v2 ...
- C++中的初始化列表
C++11扩大了列表初始化的适用范围,使其可以用于所有内置类型和用户定义的类型(即类对象). 1.当列表初始化用于内置类型的变量时,这种初始化形式有一个重要的特点:如果我们使用列表初始化且初始化值存在 ...
- CSS——可视化格式模型
CSS的可视化格式模型 CSS中规定每一个元素都有自己的盒子模型(相当一规定了这个元素如何显示): 然后可视化格式模型则是把这些盒子模型按照规则摆放到页面上,也就是如何布局: 换句话说,盒子模型规定了 ...
- Django中配置自定义日志系统
将
- PAT顶级 1002. Business (35)
PAT顶级 1002. Business (35) As the manager of your company, you have to carefully consider, for each p ...
- JQuery Easy UI 简介
[什么是JQuery Easy UI?] jQuery EasyUI 是一组基于 jQuery 的 UI 插件集合,而 jQuery EasyUI 的目标就是帮助Web 开发者更轻松的打造出功能丰富并 ...
- 关于Windows 10 初始安装的VS2013 SSDT-BI 的BUG 问题
初始安装,正常安装会出现以下出现信息,随后会被告知未安装成功. 关于SSDT-BI信息可以参见这里 http://jimshu.blog.51cto.com/3171847/1420469 从Wind ...
- Quartz.Net 学习之路01 安装Quartz.Net
Quartz.Net 系列文章的第一篇,至于Quartz.Net 是做什么的我就不介绍了,相信要用到它的都知道它是用来干嘛的: Quartz.Net安装方法: 1.打开项目,在VS“工具”菜单选中“库 ...
- 【03】《论道html5》(全)
[03] <论道html5> 共320页. 魔芋:已看完. 读后感:html5各个新特性的介绍.介绍了canvas,web socket,audio,video,web wor ...