快速幂

给定三个正整数a , b , m (a < 10^9, b < 10^18, 1 < m < 10^9),求a^b%m。

由于数据规模太大,单纯地使用循环一定会发生溢出,即使用long long。

这里要使用快速幂的做法,它基于二分思想,也被称为二分幂。快速幂基于以下事实:

  • 如果 b 是奇数, 那么有 a^b = a * a^{b-1} ;
  • 如果 b 是偶数, 那么有 a^{^{b}} = a^{b/2} * a^{b/2} ;

显然, b 是奇数的情况总可以在下一步转换为 b  是偶数的情况, 而 b 是偶数的情况总可以在下一步转换为 b 是奇数的情况。

举例, 如需求 2^{10} :

  1.  对于 2^{10} 来说 , 2^{10}2^{^{5}} * 2^{^{5}} 
  2.  对于 2^{5} 来说 ,  2^{5} = 2 * 2^{4} 
  3. 对于 2^{4} 来说  ,  2^{^{4}} = 2^{^{2}} * 2^{^{2}} 
  4. 对于 2^{ 2} 来说  ,  2^{​{2}} = 2^{​{1}} * 2^{​{1}} 
  5. 对于 2^{1} 来说  ,  2^{1} = 2 * 2^{0} 
  6. 2^{0} = 1, 然后从下往上依次回退计算即可 。

这显然是递归的思想, 于是得到快速幂的递归写法, 时间复杂度 O(logb) :


typedef long long LL;
LL binaryPow(LL a, LL b, LL m){
	if(b == 0) return 1;
	if(b % 2 == 1)
		return a * binaryPow(a, b - 1, m) % m;
	else{
		LL mul = binaryPow(a, b / 2, m);
		return mul * mul % m;
	}
	
}

PS:

  • 如果初始时 a 有可能大于等于 m, 那么需要在进入函数前就让 a 对 m 取模。
  • 如果 m 为 1, 可以直接在函数外部特判为 0, 不需要进入函数来计算 (因为任何正数对 1 取模一定为 0 )。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值