算法疑难(c++实现)---1、快速幂
一、总结
一句话总结:
比如在求a^11的时候,快速幂就是利用11的二进制1011,也即11=2º×1+2¹×1+2²×0+2³×1=1+2+8,将a^11转化为a^1*a^2*a^8,从而用O(logn)的时间复杂度求解
#include <iostream> using namespace std; int pow(int a,int n){ int ans=1,base=a; while(n){ if(n%2==1) ans=ans*base; base=base*base; n=n/2; } return ans; } int main(){ cout<<pow(2,22)<<endl; return 0; }
1、快速幂取模的原理?
根据同余定理,我们知道,(a*b)%m=((a%m)*(b%m))%m;其实快速幂取模也是用到这个
#include <iostream> using namespace std; const int mod=10007; int pow(int a,int n){ int ans=1,base=a%mod; while(n){ if(n%2==1) ans=(ans*base)%mod; base=(base*base)%mod; n=n/2; } return ans; } int main(){ cout<<pow(2,110)<<endl; return 0; }
二、快速幂
博客对应课程的视频位置:1、快速幂
https://www.fanrenyi.com/video/30/280
1、朴素求法
1 /* 2 最朴素的求幂方法 3 也就是平常使用pow函数,最简单的实现就是一直累乘 4 5 比如求a^n 6 7 */ 8 #include <iostream> 9 using namespace std; 10 11 int pow(int a,int n){ 12 int ans=1; 13 for(int i=1;i<=n;i++){ 14 ans*=a; 15 } 16 return ans; 17 } 18 19 int main(){ 20 cout<<pow(2,22)<<endl; 21 return 0; 22 } 23 24 /* 25 26 可以看到,算法的时间复杂度是O(n)。为了降低时间复杂度, 27 我们可以使用快速幂算法, 28 将时间复杂度降低到O(logn)。 29 30 */
2、快速幂
1 /* 2 3 快速幂: 4 5 首先,快速幂的目的就是做到快速求幂, 6 7 假设我们要求a^n,那么其实n是可以拆成二进制的, 8 例如当n==11时 9 11的二进制是1011, 10 11 =2º×1+2¹×1+2²×0+2³×1=1+2+8, 11 所以 12 a^11=a^1*a^2*a^8 13 原来算11次,现在只需要算三次 14 15 具体怎么算呢: 16 我们可以用一个变量base来在每次循环的时候记录a^i, 17 最开始base是a 18 然后每次循环让base=base*base 19 那么base的值 20 a-->a^2-->a^4-->a^8-->a^16-->a^32....... 21 然后根据11的二进制,1011, 22 取位为1时候的base值即可, 23 也就是取a,a^2,a^8 24 25 由此可以得到代码: 26 27 28 */ 29 30 #include <iostream> 31 using namespace std; 32 33 int pow(int a,int n){ 34 int ans=1,base=a; 35 while(n){ 36 if(n%2==1) ans=ans*base; 37 base=base*base; 38 n=n/2; 39 } 40 return ans; 41 } 42 43 int main(){ 44 cout<<pow(2,22)<<endl; 45 return 0; 46 } 47 48 49 50 /* 51 52 n 11 53 ans a 54 base a^2 55 56 n 5 57 ans a*a^2 58 base a^2*a^2=a^4 59 60 n 2 61 ans a*a^2 62 base a^4*a^4=a^8 63 64 n 1 65 ans a*a^2*a^8 66 base a^8*a^8=a^16 67 68 n 0 69 70 */
3、快速幂求模
1 /* 2 因为求幂运算得到的结果一般很大 3 所以一般需要对求幂的结果进行取模 4 所以下面就来说说快速幂取模的操作 5 6 根据同余定理,我们知道 7 (a*b)%m = ((a%m)*(b%m))%m; 8 其实快速幂取模也是用到这个 9 10 11 */ 12 13 #include <iostream> 14 using namespace std; 15 16 const int mod=10007; 17 18 int pow(int a,int n){ 19 int ans=1,base=a%mod; 20 while(n){ 21 if(n%2==1) ans=(ans*base)%mod; 22 base=(base*base)%mod; 23 n=n/2; 24 } 25 return ans; 26 } 27 28 int main(){ 29 cout<<pow(2,110)<<endl; 30 return 0; 31 }