快速幂

快速幂是一种对幂取模的快速算法,可以用a^b mod c来表示。

从最原始的开始分析,我们先用c来实现下这个函数:

int powerMod(int a, int b, int c) {
	int power = 1;
	for(int i=0;i<b;i++) {
		power *= a;
	}
	return power%c;
}

OK,这个代码不解释,分析下,时间复杂度为O(b),当然很明显这个时间复杂度并不是最大的问题,最大的问题在与当a和b的值比较大时(特别是b),power很有可能溢出。

其实很容易证明,a^b mod c = (a mod c)^b mod c,先乘再取模和先取模再乘其实是一样的,那么我们可以做出如下优化:

int powerMod(int a, int b, int c) {
	int power = 1;
	a = a%c;
	for(int i=0;i<b;i++) {
		power = (power*a)%c;
	}
	return power%c;
}

首先a先对c取模,这样可以保证每次乘上去的a都不会太大,然后可以每次都让乘积对c取模(先乘再取模和先取模再乘结果是一样的),这样的话,power溢出的问题已经解决。

当然,既然是叫快速幂,那么对于目前的时间复杂度O(b)还可以再进行优化。现在的瓶颈在与求a的b次方,循环了b次。根据a^b = (a^2)^(b/2),如果a和b都是整数,那么需要对b的奇偶性分开讨论:

b为偶数时,a^b = (a^2)^(b/2)

b为奇数时,a^b = a*(a^2)^(b/2)

这样,我们成功把O(b)降到了O(b/2),很明显这是可以递归推理的,那么最终可以降到O(log(b))。

优化后的代码:

int powerMod(int a, int b, int c) {
	int power = 1;
	a %= c;
	while(b>0) {
		if(b%2) {
			power = (power*a)%c;
		}
		b /= 2;
		a = (a*a)%c;
	}
	return power%c;
}

最终,我们优化到的时间复杂度为O(log(b)),其实上面的有些地方(比如先乘再取模和先取模再乘结果是一样的)是需要数学公式证明的,后面有时间再补上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值