快速幂
上周在牛客做了一道快速幂的题,今天整理一下,参考了睛神的《算法笔记》。
一、用处:
给定三个正整数a,b,m,计算$a^b%p$,时间复杂度O(logb);
二、原理:
形如$a^b$,
1.若b为偶数,可分解为$a^{\frac{b}{2}}*a^{\frac{b}{2}}$ 或 $(a^{2})^{\frac{b}{2}}$;
2.若b为奇数,可分解为$a^{\frac{b}{2}}*a^{\frac{b}{2}}*a$;
由此可以使用递归或者迭代计算。
三、实现:
1.递归计算,一直分解直到b为0时返回1,回溯得到结果,层数为logn;
1 typedef long long ll 2 ll binary_pow(ll a,ll b,ll p) { 3 if(b==0) return 1; 4 if(b&1) return a*binary_pow(a,b-1,p)%p; 5 else { 6 ll t=binary_pow(a,b/2,p); //细节 7 return t*t%p; 8 } 9 }
细节:如果 直接返回binary_pow(a,b/2,p)*binary_pow(a,b/2,p)%p; 需要做两次递归,降低了效率;而先赋值的方法则只进行一次递归。
2.迭代计算,将b反复折半到1,同时a反复平方,期间若b为奇数,则将当时的a累乘起来(相当于b-1),将其与最后b为1时的a相乘即为结果。
1 typedef long long ll; 2 ll binary_pow(ll a,ll b,ll p){ 3 ll t=1; 4 while(b>0){ 5 if(b&1) t=t*a%p; 6 a=(a%p)*(a%p)%p; //怕数据太大可以多取模几次 7 b>>=1; 8 } 9 return t; 10 }