快速幂+快速幂取模

快速幂是优化的幂运算算法。
快速幂取模是快速幂+同余定理。

一、暴力幂运算

考虑计算 311,可以让3累乘11次,复杂度是O(n)

int Pow1(int a, int b) {
	int ans = 1;
	for (int i = 0; i < b; i++) ans *= a;
	return ans;
}

int main() {
	cout << Pow1(3, 11) << endl;
	return 0;
}

输出:

177147

二、快速幂

以 311 举例。把指数11写成二进制形式是1011,所以
11 = 23 + 0 × 22 + 21 + 20

所以 311 又可以写成:
311 =3^ (23 + (0 × 22) + 21 + 20)

拆括号得:
311 = 38 × (0 × 34) × 32 × 31

可以发现乘法因子是以平方的形式增长的,比如 32 等于 31 的平方,38 等于 34 的平方。
由此规律,可以写出快速幂算法了。
我们先定义一个ans=1来保存答案,然后从低到高遍历指数b的每一个二进制位,同时我们让底数a随着循环每次做一个平方,a, a2, a4, a8,…。
可以写出快速幂的框架:

int Pow(int a, int b) {
	int ans = 1;
	while (b) {
		...
		a *= a;
		b >>= 1;
	}
	return ans;
}

因为11是1011,311 = 38 × (0 × 34) × 32 × 31,可以发现,当二进制位等于1时,ans要累乘一次a。因此完整代码如下:

#include <iostream>
using namespace std;

int Pow(int a, int b) {
	int ans = 1;
	while (b) {
		//因为1的二进制是0000 0001,所以 b & 1 为真就意味着 b 的最低位是1。
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

int main() {
	cout << Pow(3, 11) << endl;
	return 0;
}

以上就是快速幂算法的分析。

三、快速幂取模

快速幂取模可以用来解决 “1145141919810 除以6的余数等于多少”或者是“230的后6位是多少”之类的问题。它是在快速幂的基础上,结合了同余定理。

#include <iostream>
using namespace std;

int Pow(int a, int b, int c) {
	int ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % c;
		a = a * a % c;
		b >>= 1;
	}
	return ans;
}

int main() {
	cout << Pow(114514, 1919810, 6) << endl;
	cout << Pow(2, 30, 1000000) << endl;
	return 0;
}

输出:

4
741824
发布了105 篇原创文章 · 获赞 24 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Kwansy/article/details/103655469
今日推荐