快速幂
快速幂顾名思义,就是快速算某个数的多少次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。
目录 | 1定义 | 2原理 | 3实现 |
---|
折叠 定义
快速幂顾名思义,就是快速算某个数的多少次幂。
其时间复杂度为 O(log2N), 与朴素的O(N)相比效率有了极大的提高。
以下以求a的b次方来介绍
折叠 原理
把b转换成2进制数
该2进制数第i位的权为(2^(i-1))
例如
a^11=a^(2^0+2^1+2^3)
11的二进制是1 0 1 1
11 = 2^3*1 + 2^2*0 + 2^1*1 + 2^0*1
因此,我们将a^11转化为算a^(2^0)*a^(2^1)*a^(2^3)[1]
折叠 编辑本段 实现
快速幂可以用位运算这个强大的工具实现
b and 1 //也就是取b的二进制最末位
b shr 1 //就是去掉b的二进制最末位
有了这个强大的工具,快速幂就好实现了!
var
a,b,n:int64;
function f(a,b,n:int64):int64;
var
t,y:int64;
begin
t:=1;y:=a;
while b<>0 do
begin
if (b and 1)=1 then t:=t*y mod n;
y:=y*y mod n; //这里用了一个很强大的技巧,y*y即求出了 a^(2^(i-1)) ←不知道这是什么的看原理
b:=b shr 1;
end;
exit(t);
end;
begin
read(a,b,n); // n是模
write(f(a,b,n));
end.[1]
编辑本段
代码比较
常规求幂
1
2
3
4
5
6
int pow1( int a, int b ) {
int r = a;
while( b-- )
r *= a;
return r;
}
二分求幂(一般)
1
2
3
4
5
6
7
8
9
10
int pow2( int a, int b ) {
int r = 1, base = a;
while( b != 0 ) {
if( b % 2 )
r *= base;
base *= base;
b /= 2;
}
return r;
}
快速求幂(位操作)
1
2
3
4
5
6
7
8
9
10
int pow3( int a, int b ) {
int r = 1, base = a;
while( b != 0 ) {
if( b & 1 )
r *= base;
base *= base;
b >>= 1;
}
return r;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
快速求幂(更高效率的位运算法)
int power4(int x, int n)
{
if (n == 0)
{
return 1;
}
else
{
while ((n & 1) == 0)
{
n >>= 1;
x *= x;
}
}
int result = x;
n >>= 1;
while (n != 0)
{
x *= x;
if ((n & 1) != 0)
result *= x;
n >>= 1;
}
return result;
}