快速幂

像这样,将指数除以2.如果不可以被2整除,将目前底数拿出一个。无论是否被2整除,都需要更新底数和指数。

c为要被取模的数(a的b次方mod  c)

这个并不够优化

 1 private static long fast_power(long a,long b){
 2       long res = 1;
 3     while(b>0){
 4       if((b&1)>0){
 5         res = (res*a)%mod;
 6       }
 7       a = (a*a)%mod;
 8       b>>=1;
 9     }
10     return res;
11     }
 1 //非递归快速幂
 2 int qpow(int a, int n){
 3     int ans = 1;
 4     while(n){
 5         if(n&1)        //如果n的当前末位为1
 6             ans *= a;  //ans乘上当前的a
 7         a *= a;        //a自乘
 8         n >>= 1;       //n往右移一位
 9     }
10     return ans;
11 }

这里的位运算符,>>是右移,表示把二进制数往右移一位,相当于/2;&是按位与,&1可以理解为取出二进制数的最后一位,相当于%2==1。这么一等价,是不是看出了递归和非递归的快速幂的关系了?虽然非递归快速幂因为牵扯到二进制理解起来稍微复杂一点,但基本思路其实和递归快速幂没有太大的出入。

快速幂的拓展

上面所述的都是整数的快速幂,但其实,在算 a的n次方 时,只要a的数据类型支持乘法且满足结合律,快速幂的算法都是有效的。矩阵、高精度整数,都可以照搬这个思路。下面给出一个模板:

 1 //泛型的非递归快速幂
 2 template <typename T>
 3 T qpow(T a, ll n)
 4 {
 5     T ans = 1; // 赋值为乘法单位元,可能要根据构造函数修改
 6     while (n)
 7     {
 8         if (n & 1)
 9             ans = ans * a; // 这里就最好别用自乘了,不然重载完*还要重载*=,有点麻烦。
10         n >>= 1;
11         a = a * a;
12     }
13     return ans;
14 }

 

posted @ 2024-02-28 16:04  小菜碟子  阅读(1)  评论(0编辑  收藏  举报