[算法]快速幂

(基本上是从百度百科搬过来的,虽然本大佬是宇宙无敌牛逼,但是有错还请指出~谢谢,有空请你一起抠脚~么么哒)

求底数为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) ” 是不是就清晰易懂了呢?

至于递归的代码,这里就不给了,百度百科里面都有,感谢亲亲看完哟~

 

posted @ 2020-04-27 22:41  小贼的自由  阅读(525)  评论(0编辑  收藏  举报