快速幂及快速幂取模
数学基础
快速幂
当我们求取公式
我们不妨转换一种思路,首先将
将其代入
定义第
由于
模运算
虽然快速幂算法能够在幂运算的指数很大时非常快地求出结果,但通常情况下,我们求如此大的指数幂,并不是为了得到目标结果,而是为了得到目标结果对某个数的余数,这在现代密码学中十分常见。
在实际的应用中,由于目标结果通常非常大,远远超出了计算机的存储能力,而我们需要的只是结果对于某个数的余数,,所以我们需要应用一些模运算的技巧来简化运算。
以下是模运算中最基本的一些公式,其中除法并不能简单的进行运算,详见乘法逆元:
我们发现,快速幂算法中实际上只用到了乘法,所以可以利用模运算的特点将取模的运算直接添加到所有会影响最终结果的乘法计算中,则最终的计算结果正是我们需要的结果。
代码
幂运算的结果可能很大,应当注意数据类型以避免溢出!
快速幂
ts
/**
* number类型支持的最大安全整数仅有2^53-1,大约为9e15
* 在幂运算中非常容易溢出,建议使用更安全的bigint
*/
export function quickPower(x: bigint, p: bigint): bigint {
let res: bigint = 1n;
while (p) {
if (p & 1n) res *= x;
x *= x;
p >>= 1n;
}
return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
py
def quick_power(x: int, p: int) -> int:
res: int = 1
while p:
if p & 1:
res *= x
x *= x
p >>= 1
return res
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
快速幂取模
ts
/**
* number类型支持的最大安全整数仅有2^53-1,大约为9e15
* 在幂运算中非常容易溢出,建议使用更安全的bigint
*/
export function quickMod(x: bigint, p: bigint, mod: bigint): bigint {
let res: bigint = 1n;
while (p) {
if (p & 1n) res = (res * x) % mod;
x = (x * x) % mod;
p >>= 1n;
}
return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
py
def quick_mod(x: int, p: int, mod: int) -> int:
res: int = 1
while p:
if p & 1:
res = (res * x) % mod
x = (x * x) % mod
p >>= 1
return res
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8