(基本上是从百度百科搬过来的,虽然本大佬是宇宙无敌牛逼,但是有错还请指出~谢谢,有空请你一起抠脚~么么哒)
求底数为a的n次幂:
一般解法都是“a*a*a……*a”,复杂度为O(n);
下面是快速幂解法:
1.把n转换为二进制,例如:
11转换为二进制1011;
2.将n得到的二进制以“数位的值*权值”的和表示,例如:
11可表示为“1*(2^3)+0*(2^2)+1*(2^1)+1*(2^0)”;
3.由第2点可以得到a的11次方为:
a^(1*(2^3))*a^(0*(2^2))*a^(1*(2^1))*a^(1*(2^0));
那么就可得以下代码(下面的代码将结果取模了,因为一般的运算结果过于庞大,题目或者实际都是要求是将结果取模,如果不需要取模自行删除即可),时间复杂度是O(log2n):
1 #include<iostream> 2 using namespace std; 3 int main()//计算a^n % mod 4 { 5 long long a, n, mod; 6 long long re = 1; 7 cin>>a>>n; 8 while(n) 9 { 10 if(n & 1){//判断n的最后一位是否为1 11 re = (re * a) % mod; 12 } 13 n >>= 1;//移位操作,去掉n的最后一位 14 a = (a * a) % mod; 15 /*这里用了一个技巧,a*a即求出了a^(2^(i-1)) 16 *不知道这是什么的看原理 17 *a^(2^(i-1))*a^(2^(i-1))=a^(2^i) 18 *而且一般情况下a*b mod c =(a mod c)*(b mod c) mod c*/ 19 } 20 cout<< re % mod; 21 return 0; 22 }
需要注意的是,可能很多人都看不懂14行的含义:
a = (a * a) % mod;
不理解的话就只能是生搬硬套的模板,没有任何意义。虽然代码注释里都说了,但是还是得讲一下自己的理解,我也怕以后忘记了,还是以a的11次方为例:
由于n的二进制的数位的值只会是1和0,因此上面第3点得到的式子中的1省去,有:
a^(1*(2^3))*a^(0*(2^2))*a^(1*(2^1))*a^(1*(2^0)) => a^(2^3) * a^(0*(2^2)) * a^(2^1) * a^(2^0)
看到上式2的指数,那么注释里的 “ a^(2^(i-1))*a^(2^(i-1))=a^(2^i) ” 是不是就清晰易懂了呢?
至于递归的代码,这里就不给了,百度百科里面都有,感谢亲亲看完哟~