快速幂第二章(C++循环迭代版本)
既然是第二章,那当然有第一章啦!详见快速幂第一章(C++递归版本)。
如果您想要更加透彻地学习快速幂的知识,请务必将这篇文章细细地,一字不落地看完。
前言
当题目要我们求类如 a b = ? a^b=? ab=?的题目时,最直接,最暴力的写法如下:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
int main() {
LL a,b,res=1;
cin>>a>>b;
while(b--) {
res*=a;
}
cout<<res;
}
算法简单明了,循环 b b b次,每次答案 × a ×a ×a。而这类代码,往往是TLE。
TLE很好理解。这段代码的时间复杂度是 O ( b ) O(b) O(b)。当b的数据范围很大时自然会超时。
(时间复杂度如何计算可以参考编者的另一篇博客大 O O O时间复杂度详解)
关于幂的知识
- a b = a × a × . . . × a × a a^b=a×a×...×a×a ab=a×a×...×a×a( b b b个 a a a相乘)
- a x × a y a^x×a^y ax×ay
= a × a × . . . × a \red a\red ×\red a\red×\red.\red.\red.\red×\red a a×a×...×a ( x (x (x个 a ) a) a) × × × a × a × . . . × a × a \blue a\blue ×\blue a\blue ×\blue .\blue .\blue .\blue ×\blue a\blue ×\blue a a×a×...×a×a ( y (y (y个 a ) a) a)
= ( x + y ) (x+y) (x+y)个 a a a相乘的积
= a x + y a^{x+y} ax+y
例如 2 3 × 2 5 = 2 8 2^3×2^5=2^8 23×25=28
进制转换
对于 10 10 10进制转成 x x x进制,我们可以采用除以 x x x取余法:
这是一种常见的手工计算方法,适用于整数。具体步骤如下:
将十进制数不断除以 x x x,直到商为 0 0 0为止,取得的余数从下往上依次排列,即为 x x x进制数的结果。
例如:将十进制数 11 11 11转换为二进制:
第一步: 11 ÷ 2 = 5...1 11÷2=5...1 11÷2=5...1
第二步: 5 ÷ 2 = 2...1 5÷2=2...1 5÷2=2...1
第三步: 2 ÷ 2 = 1...0 2÷2=1...0 2÷2=1...0
第四步: 1 ÷ 2 = 0...1 1÷2=0...1 1÷2=0...1
将得到的余数从上往下排列,得到的结果为 1101 1101 1101
1101 1101 1101是 11 11 11的二进制形式的逆序数(倒过来)。
将 1101 1101 1101反过来, 1011 1011 1011即为所求十进制数 11 11 11的二进制形式。
正文
为了直观简洁,这里用字母 D \scriptsize D D和 B \scriptsize B B表示十进制标识和二进制表标识
比如下面的 5 ( D ) 5\scriptsize(D) 5(D)表示十进制数 5 5 5, 101 ( B ) 101\scriptsize(B) 101(B)表示二进制数 101 101 101。
5 ( D ) 5\scriptsize(D) 5(D) = 101 =101 =101 ( B ) \scriptsize(B) (B)
= 100 ( B ) =100\scriptsize(B) =100(B) + 1 +1 +1 ( B ) \scriptsize(B) (B)
= 4 ( D ) =4\scriptsize(D) =4(D) + 1 +1 +1 ( D ) \scriptsize(D) (D)
很容易理解吧?
用这种方式,我们可以将任一个数字拆分成若干个 2 2 2的幂次方数相加的形式。
如 11 = 8 + 2 + 1 , 21 = 16 + 4 + 1 , 15 = 8 + 4 + 2 + 1 11=8+2+1,21=16+4+1,15=8+4+2+1 11=8+2+1,21=